2

株式市場で作業する場合、28 日平均、14 日平均などを含む計算指標を計算する必要があります。

さらに、最新の日の終値/高値/安値/出来高を含めるために、毎日平均値を更新する必要があります。

多くの場合、配列をループして、合計、平均、最大、および最小値を見つける必要があります。

入口/出口の FIFO 方式に基づくキュー (動的配列またはリンクされたリストなどの形式) は、これに最適なデータ構造のように思えます。

質問:

  1. ハッシュと比較して、キューの効率とスケーラビリティはどうですか?
  2. Perlスクリプトを実行すると、キューはメモリ内にないため、初期化して処理する必要があります(値はCSVファイルから初期化されます)。これはあまり関係がないことはわかっていますが、毎日のスケジュールで実行される Perl スクリプト?
4

6 に答える 6

2

PDLを使用すると、より大きな「配列」(1D マトリックス) のスライスを取得し、そのスライスで統計を実行してから、別のスライスを取得して繰り返すことができます。PDL には多くの組み込みの統計関数があり、それで十分でない場合は、アドオンPDL::Statsがあります。

PDL は、Perl の MatLab や NumPy (より良いと思います!) のようなものです。数値配列の「ループ」に対して高度に最適化されています。「ループ」を引用符で囲んだのは、これらのループが C レベルで実装されているためです (速いですね?)。のぞいてみてください!

于 2013-02-05T21:23:32.880 に答える
1

ここでは十分な情報がありません。毎日の高値/安値/終値を取得するために、1 日分のクオートを処理していますか?

楽器ごとに平均を取っていますか?

どの移動平均でも、平均の合計を構成する値のリストを使用できます。新しい値が追加されると、1 つが削除され、再計算されます。

したがって、リストのハッシュは、楽器で実行し、その場で計算する場合です。

于 2013-02-05T20:34:06.240 に答える
1

最も効率的なものは実際には異なります。

  • ハッシュは順不同です。文字列キーによって、ほぼ一定の時間で値を検索できます。ルックアップは計算コストが高く、少なくとも配列ルックアップよりも 1 桁遅くなります。ハッシュのパフォーマンスは、「バケット」の数とキーの数によって異なります。ただし、ハッシュ ルックアップは、すべての重要なケースの要素を見つけるために配列をループするよりも高速です。ハッシュは、配列よりも多くのスペースを必要とします。
  • Perl の配列には、配列 (ランダム アクセス) と二重にリンクされたリスト (プッシュ、ポップ、シフト、シフト解除による) の両方の特性があります。それらは使いやすく、十分に高速です。複数の要素を追加/削除する場合は、スライスまたはsplice関数を使用します。splicepush..の一般化でありunshift、ループよりも高速です。
  • 文字列を使用して、整数の配列を格納できます。これは非常に効率的ですが、非常に制限されています (int のみ)。

    my $string = "";
    my $i = ~ 0; # a really big number
    $string .= chr $i; # get character from integer
    # Access elements via `substr`:
    my $j = ord substr $string, -1, 1; # last element; ord gets an int from a char
    

    文字列の使用には、配列 (ランダム アクセス) と単一の連結リスト (追加は で簡単.=) の特徴があります。他の操作もかなり高速です (substr多くの用途があります)。

実用的なプログラマは、ほとんどのシーケンシャル データに配列を使用します。また、 、、および(速度を上げるために C で記述)などの関数を提供するList::Utilおよびの効率的な関数を利用することもできます。List::MoreUtilssumaveragemaxmin

値のリストを作成していて、固定量のみが必要な場合は、新しい要素を追加するときに次のようにします。

push @array, $new_value;
shift @array if @array > $max_length; # keep constant length

これはスペース効率に優れていますが、単純にリストを作成して実行するよりも遅くなる可能性があります。

splice @array, 0, -$max_length; # remove all but $max_length last elems

(新しい変数を割り当てずに) 配列の特定の部分のみにアクセスするには、スライスを使用します。

use List::Util qw/sum/;
my $last_24_sum = sum @array[-24 .. $#$array];  sum the last 24 elems

ハッシュを使用したいが、コンパイル時にすべての可能なフィールドを知っている場合は、フィールドの定数名を定義し、代わりに配列を使用できます。だからしないでください

my $hashref = { foo => $x, bar => $y }; # requires a lot of space
$hashref->{foo}; # slooow

しかし、する

use constant {
    EL_FOO => 0, # make sure the integer range is continouus
    EL_BAR => 1, #   Perl doesn't have native enums
};
my $arrayref = [$x, $y];
$arrayref->[EL_FOO]; # faster!

代わりは。

深くネストされたデータを操作する場合、ネストされた参照をアクセスごとに再計算するのではなく、キャッシュすることで成果が得られることがあります。

# disputable
for my $i (...) {
  for my $j (...)
    do_something_with $x->[$i][$j][$_] for 1 .. 1e3;
  }
}
# possibly better
for my $i (...) {
  for my $j (...) {
    my $aref = $x->[$i][$j];
    do_something_with $aref->[$_] for 1 .. 1e3;
  }
}
于 2013-02-05T22:47:20.577 に答える
1

これらを 1 日に 1 回計算する場合は、最も簡単なデータ構造を使用してコーディングしてください。計算するのに本当にそんなに時間がかかりますか?はいの場合は、読み続けてください。

合計と平均の方が簡単かもしれません。追加するものが整数の場合、FIFO を使用して合計を変数に保持できます。要素を挿入または削除するたびに、それに応じて合計を更新します (加算または減算)。

浮動小数点値を追加すると、上記の方法で累積エラーが発生する可能性があります。これは、値の大きさが大きく異なる場合や、系列が非常に長い場合に発生する可能性があります。この場合、もっと複雑なものが必要になります (以下を参照)。

最大および最小の場合、最も効率的なデータ構造はmax/min-heapsです。それらを配列に埋め込むことができることに注意してください。毎回削除する必要がある要素をすぐに見つけるために、FIFO キューの要素と相互参照する必要があります。

最も一般的な解決策は、拡張自己平衡ツリーです。拡張データ構造については、Cormen、Leiserson、Rivest、および Stein による「Introduction to Algorithms」の第 14 章で説明されています。基本的に、ツリーにはすべてのノードにデータ シーケンスの 1 つの要素が含まれます。すべてのノードには、そのサブツリーの合計、最小、および最大も含まれます。ノードを更新するたびに、そのノードからルートまでのすべてのパスの合計、最大、最小を更新する必要があります。ルートには、グローバル合計の最大値と最小値があります。

拡張自己均衡ツリーの C++ 実装は、こちら にあります。

ただし、固定数の要素の合計、最小、最大のみが必要であり、常に一方の端で挿入し、もう一方の端で削除するため、はるかに簡単にすることができます。循環バッファーと配列埋め込みツリーのみが必要です(このようなツリーを配列に埋め込む方法を参照してください)。ツリーには、前述の拡張ツリーのように、部分的な合計、最小値、および最大値が含まれます。利点は、シーケンスの途中で挿入/削除することがなく、ツリーが常に同じサイズであるため、ツリーのバランスを取り直す必要がないことです。

過去 28 日間、過去 14 日間、先週、および過去 3 日間 (たとえば) の統計を取得するには、すべての期間に対して循環バッファーと配列組み込みツリーを使用します。過去 3 日間、過去 4 (7 マイナス 3) 日間の別、過去 7 日間の別、というように続きます。毎日、すべてのバッファの最後のデータを取得して、次のバッファに挿入します。

于 2013-02-06T06:54:44.900 に答える
0

実行ごとにゼロからデータを完全に再構築している場合は、おそらくStatistics::Descriptiveを調べる必要があります。

これをCSVとして取得しているのは残念です。データベース サーバーにアクセスすると、いくつかの SQL クエリでこの情報を取得できます。

于 2013-02-05T20:34:39.890 に答える
0

%hashタイムスタンプの文字列化または数値化された表現であるキーと、データがその時系列アイテムに関連付けられている値である単純なものを使用します。ハッシュのキーを並べ替えることができます。

#numeric
@srtdKeys = sort{$a<=>$b}(keys(%hash));

また

#string
@srtdKeys = sort(keys(%hash));

最後の 28 または 14 などをループし、ハッシュから値を取得します。

于 2013-02-05T20:23:50.077 に答える