在股票市场上工作时,需要计算包括28天平均值,14天平均值等计算指标。
此外,每天平均需要更新,以包括最近一天的收盘价/高/低价/成交量。
现在,数组需要循环才能找到sum,average,max和min值。
我认为一个队列(以动态数组或链表的形式或者你能想到的任何其他东西)看起来像是基于进入/退出的FIFO方法的完美数据结构。
问题:
答案 0 :(得分:2)
使用PDL,您可以获取一个更大的“数组”(1D矩阵),然后对该切片进行统计,然后再取另一个切片并重复。 PDL有许多内置的统计函数,如果还不够,还有附加PDL::Stats!
对于Perl,PDL就像MatLab或NumPy(我们认为更好!)。它针对数值阵列的“循环”进行了高度优化。我把“循环”放在引号中,因为这些循环是在C级实现的(听起来很快啊?)。看一看!
答案 1 :(得分:1)
此处信息不足。您是否处理了整天的报价以获得每日高/低/最后?
您是否按照每个工具进行平均值?
对于任何移动平均线,您只需使用构成平均值总和的值列表。随着新值的增加,一个值下降,并重新计算。
如果您通过仪器进行操作并在运行中计算,那么就是列表的散列。
答案 2 :(得分:1)
最有效的是什么。
splice
函数。 splice
是push
.. unshift
的概括,并且比循环更快。字符串可用于存储整数数组。这非常有效,但也非常有限(仅限整数)。
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
有很多用途)。
实用程序员将使用数组来处理大多数顺序数据。他还可以利用List::Util
和List::MoreUtils
中提供sum
,average
,max
和min
等函数的高效函数(用C语言编写)速度)。
当您构建值列表并且只需要固定数量时,请在添加新元素时执行此操作:
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;
}
}
答案 3 :(得分:1)
如果您每天计算一次这些东西......使用最简单的数据结构进行编码!计算真的需要这么多时间吗?如果是,请继续阅读。
总和和平均值可能更容易。如果添加的是整数,则可以使用FIFO并将总和保存在变量中。无论何时插入或删除元素,都要相应地更新总和(加或减)。
如果添加浮点值,则上述方法可能会导致累积错误。如果值具有非常不同的大小和/或系列非常长,则可能发生这种情况。在这种情况下,您需要更复杂的东西(见下文)。
对于max和min,最有效的数据结构是max/min-heaps。请注意,您可以将它们嵌入到数组中。您需要将它们与FIFO队列的元素进行交叉引用,以便立即找到每次都必须删除的元素。
最通用的解决方案是增强的自平衡树。增强数据结构在"算法简介"的第14章中进行了解释。由Cormen,Leiserson,Rivest和Stein。基本上,树将在每个节点中包含数据序列的一个元素。每个节点还包含其子树的和,最小值和最大值。每次更新节点时,都必须更新从该节点到根节点的所有路径中的sum,max和min。在根中你有全局和,最大和最小。
您可以找到扩充自平衡树here的C ++实现。
虽然,因为你只需要固定数量元素的总和,最小值和最大值,并且你总是在一端插入而在另一端删除,你可以使它更简单。您只需要一个循环缓冲区和一个嵌入数组的树(参见how to embed such tree in an array)。树将包含部分和,最小和最大值,如前面描述的增强树。优点是您不需要重新平衡树,因为您从不在序列的中间插入/删除树,并且树总是具有相同的大小。
为了获得过去28天,过去14天,最后一周和过去3天(例如)的统计信息,您将为每个时段使用循环缓冲区和数组嵌入树:一个用于过去3天,另一个用于前4天(7减3)天,另一个用于前7天,依此类推。每天,您将获取每个缓冲区的最后一个数据并将其插入下一个缓冲区。
答案 4 :(得分:0)
我只使用一个简单的%hash
,其中键是时间戳的字符串化或数字化表示,值是您的数据与该时间序列项相关联的值。您可以对哈希的键进行排序,例如
#numeric
@srtdKeys = sort{$a<=>$b}(keys(%hash));
或
#string
@srtdKeys = sort(keys(%hash));
并遍历最后的28或14等,然后从散列中检索值。
答案 5 :(得分:0)
如果您在每次运行时从头开始重建数据,也许您应该查看Statistics::Descriptive。
很遗憾你是以CSV形式获得的。通过访问数据库服务器,您可以通过几个SQL查询获取此信息。