指数移動平均を算出する
指数移動平均を算出するライブラリです。
- ちょっとリファクタして、移動平均や加重移動平均と共通部分を親クラスに移動しています。ファイルも1つに統合して、APIも微妙に修正してます。
- あと、加重移動平均の加重が逆(古いものを重視)だったのも修正してます。orz.
module Signal #===一定期間のレートデータを元に値を算出するシグナルの基底クラス class RangeSignal def initialize( range=25 ) @datas = [] # レートを記録するバッファ @range = range end def next_data( data ) # バッファのデータを更新 @datas.push data @datas.shift if @datas.length > @range # バッファサイズが十分でなければ、nilを返す。 return nil if @datas.length != @range # 算出 return calculate(@datas) end def calculate(datas) end end #===移動平均 class MovingAverage < RangeSignal def calculate(datas) MovingAverage.ma( datas ) end # 移動平均値を計算する。 def self.ma( datas ) total = datas.inject {|t,s| t += s; t } return total / datas.length end end #===加重移動平均 class WeightedMovingAverage < RangeSignal def calculate(datas) WeightedMovingAverage.wma( datas ) end # 加重移動平均値を計算する。 def self.wma( datas ) weight = 1 total = datas.inject(0.0) {|t,s| t += s * weight weight += 1 t } return total / ( datas.length * (datas.length+1) /2 ) end end #===指数移動平均 class ExponentialMovingAverage < RangeSignal def initialize( range=25, smoothing_coefficient=0.1 ) super(range) @sc = smoothing_coefficient end def calculate(datas) ExponentialMovingAverage.ema( datas, @sc ) end # 指数移動平均値を計算する。 def self.ema( datas, smoothing_coefficient ) datas[1..-1].inject( datas[0] ) {|t,s| t + smoothing_coefficient * (s - t) } end end end
移動平均、加重移動平均、指数移動平均のグラフを表示するエージェントのサンプルです。
# # 移動平均をいろいろ試してみるエージェントのサンプル # class MovingAveragesAgent < JIJI::PeriodicallyAgent include JIJI::Agent::Shared::Signal # エージェントの説明 def description "移動平均、加重移動平均、指数移動平均を表示する" end # エージェントを初期化する。 def init @mvs = [ MovingAverage.new(@range), WeightedMovingAverage.new(@range), ExponentialMovingAverage.new(@range) ] @out = output.get( "移動平均,加重移動平均,指数移動平均", :graph, { :column_count=>3, :graph_type=>:rate, :colors=>["#8899aa","#aa8899","#99aa88"] } ) end # 次のレートを受け取る def next_period_rates( rates ) res = @mvs.map{|mv| mv.next_data( rates[:EURJPY].bid.end ) } return if ( !res[0] || !res[1] || !res[2] ) @out.put( *res ) end # UIから設定可能なプロパティの一覧を返す。 def property_infos super().concat [ Property.new( "range", "集計期間", 25, :number ) ] end end