unageanu-jiji 1.1.4 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +24 -1
- data/README +0 -0
- data/base/shared_lib/moving_average.rb +34 -33
- data/base/shared_lib/system/cross.rb +76 -0
- data/base/shared_lib/system/position_manager.rb +160 -0
- data/base/shared_lib/system/signal.rb +347 -0
- data/html/css/datatable.css +4 -4
- data/html/css/default.css +57 -5
- data/html/css/treeview.css +205 -0
- data/html/img/bin_closed.png +0 -0
- data/html/img/bin_empty.png +0 -0
- data/html/img/button_add_small.gif +0 -0
- data/html/img/button_add_small_gray.gif +0 -0
- data/html/img/button_add_small_over.gif +0 -0
- data/html/img/button_mkcol.gif +0 -0
- data/html/img/button_mkcol_gray.gif +0 -0
- data/html/img/button_mkcol_over.gif +0 -0
- data/html/img/button_remove_small.gif +0 -0
- data/html/img/button_remove_small_gray.gif +0 -0
- data/html/img/button_remove_small_over.gif +0 -0
- data/html/img/button_rename.gif +0 -0
- data/html/img/button_rename_gray.gif +0 -0
- data/html/img/button_rename_over.gif +0 -0
- data/html/img/control_play.png +0 -0
- data/html/img/control_play_blue.png +0 -0
- data/html/img/folder.png +0 -0
- data/html/img/folder_brick.png +0 -0
- data/html/img/folder_user.png +0 -0
- data/html/{js/codepress/images → img}/line-numbers.png +0 -0
- data/html/img/page_white_ruby.png +0 -0
- data/html/img/sidebar_agent_edit.png +0 -0
- data/html/img/sidebar_agent_edit_over.png +0 -0
- data/html/img/sidebar_agent_edit_s.png +0 -0
- data/html/img/yui/treeview-sprite.gif +0 -0
- data/html/index.html +34 -18
- data/html/js/agent-editor/agent-editor-page.js +324 -0
- data/html/js/agent-editor/agent-editor.js +363 -0
- data/html/js/agent-editor/agent-list-tree.js +251 -0
- data/html/js/agent-selector.js +23 -28
- data/html/js/app.js +63 -91
- data/html/js/bt-create-page.js +25 -19
- data/html/js/container-min.js +1 -1
- data/html/js/container.js +944 -0
- data/html/js/edit_area/autocompletion.js +11 -13
- data/html/js/edit_area/edit_area.css +79 -40
- data/html/js/edit_area/edit_area.js +255 -226
- data/html/js/edit_area/edit_area_compressor.php +4 -4
- data/html/js/edit_area/edit_area_full.gz +0 -0
- data/html/js/edit_area/edit_area_full.js +31 -31
- data/html/js/edit_area/edit_area_full_with_plugins.gz +0 -0
- data/html/js/edit_area/edit_area_full_with_plugins.js +31 -31
- data/html/js/edit_area/edit_area_functions.js +448 -341
- data/html/js/edit_area/edit_area_loader.js +409 -397
- data/html/js/edit_area/elements_functions.js +120 -123
- data/html/js/edit_area/highlight.js +305 -197
- data/html/js/edit_area/images/goto.png +0 -0
- data/html/js/edit_area/images/help.png +0 -0
- data/html/js/edit_area/images/redo.png +0 -0
- data/html/js/edit_area/images/save.png +0 -0
- data/html/js/edit_area/images/search.png +0 -0
- data/html/js/edit_area/images/undo.png +0 -0
- data/html/js/edit_area/images/word_wrap.gif +0 -0
- data/html/js/edit_area/keyboard.js +5 -5
- data/html/js/edit_area/langs/bg.js +73 -0
- data/html/js/edit_area/langs/cs.js +2 -0
- data/html/js/edit_area/langs/de.js +2 -0
- data/html/js/edit_area/langs/dk.js +2 -0
- data/html/js/edit_area/langs/en.js +2 -0
- data/html/js/edit_area/langs/eo.js +2 -0
- data/html/js/edit_area/langs/es.js +2 -0
- data/html/js/edit_area/langs/fi.js +67 -0
- data/html/js/edit_area/langs/fr.js +2 -0
- data/html/js/edit_area/langs/hr.js +2 -0
- data/html/js/edit_area/langs/it.js +2 -0
- data/html/js/edit_area/langs/ja.js +2 -0
- data/html/js/edit_area/langs/mk.js +2 -0
- data/html/js/edit_area/langs/nl.js +2 -0
- data/html/js/edit_area/langs/pl.js +2 -0
- data/html/js/edit_area/langs/pt.js +2 -0
- data/html/js/edit_area/langs/ru.js +2 -0
- data/html/js/edit_area/langs/sk.js +2 -0
- data/html/js/edit_area/langs/zh.js +67 -0
- data/html/js/edit_area/manage_area.js +362 -205
- data/html/js/edit_area/plugins/charmap/langs/bg.js +12 -0
- data/html/js/edit_area/plugins/charmap/langs/zh.js +6 -0
- data/html/js/edit_area/plugins/test/langs/bg.js +10 -0
- data/html/js/edit_area/plugins/test/langs/zh.js +4 -0
- data/html/js/edit_area/reg_syntax/java.js +56 -0
- data/html/js/edit_area/reg_syntax/ruby.js +9 -9
- data/html/js/edit_area/reg_syntax.js +15 -13
- data/html/js/edit_area/regexp.js +36 -32
- data/html/js/edit_area/resize_area.js +43 -47
- data/html/js/edit_area/search_replace.js +29 -29
- data/html/js/edit_area/template.html +6 -4
- data/html/js/json-broker-client.js +23 -17
- data/html/js/result-page.js +107 -57
- data/html/js/rt-setting-page.js +38 -15
- data/html/js/sidebar.js +41 -27
- data/html/js/templates.js +167 -32
- data/html/js/utils.js +143 -7
- data/html/js/yui/treeview.js +3671 -0
- data/html/swf/chart.swf +0 -0
- data/html/test/agent_editor_spec.js +815 -0
- data/html/test/index.html +40 -0
- data/html/test/jsspec/JSSpec.css +224 -0
- data/html/test/jsspec/JSSpec.js +1549 -0
- data/html/test/jsspec/diff_match_patch.js +1 -0
- data/html/test/utils_spec.js +111 -0
- data/lib/jiji/agent/agent.rb +69 -12
- data/lib/jiji/agent/agent_manager.rb +18 -12
- data/lib/jiji/agent/agent_registry.rb +35 -121
- data/lib/jiji/collector.rb +16 -6
- data/lib/jiji/command.rb +46 -5
- data/lib/jiji/dao/file_system_dao.rb +158 -0
- data/lib/jiji/dao/timed_data_dao.rb +2 -0
- data/lib/jiji/dao/trade_result_dao.rb +1 -1
- data/lib/jiji/error.rb +24 -8
- data/lib/jiji/migration/migrator1_2_0.rb +67 -0
- data/lib/jiji/models.rb +82 -24
- data/lib/jiji/operator.rb +55 -51
- data/lib/jiji/output.rb +85 -29
- data/lib/jiji/output_manager.rb +84 -0
- data/lib/jiji/plugin/embedded/single_click_client.rb +2 -2
- data/lib/jiji/plugin/securities_plugin.rb +0 -1
- data/lib/jiji/process.rb +229 -208
- data/lib/jiji/process_manager.rb +190 -96
- data/lib/jiji/registry.rb +87 -19
- data/lib/jiji/server.rb +1 -0
- data/lib/jiji/service/agent_service.rb +147 -48
- data/lib/jiji/service/output_service.rb +37 -17
- data/lib/jiji/service/process_service.rb +3 -5
- data/lib/jiji/service/trade_result_service.rb +4 -5
- data/lib/jiji/util/file_lock.rb +4 -4
- data/lib/jiji/util/include_proxy.rb +17 -0
- data/lib/jiji/util/json_broker.rb +6 -4
- data/lib/jiji/util/util.rb +1 -1
- data/swf/chart/fx/chart/Chart.as +7 -0
- data/swf/chart/fx/chart/ui/graph/GraphManager.as +15 -2
- data/test/ProcessTest/agents/foo.rb +10 -0
- data/test/ProcessTest/conf/configuration.yaml +3 -0
- data/test/agent/agent_tests.rb +10 -0
- data/test/agent/test_AgentManager.rb +28 -12
- data/test/agent/test_AgentRegistry.rb +194 -99
- data/test/agent/test_PeriodicallyAgent.rb +1 -2
- data/test/agent/test_Permitter.rb +1 -2
- data/test/all_tests.rb +7 -19
- data/test/dao/dao_tests.rb +9 -0
- data/test/dao/test_FileSystemDao.rb +431 -0
- data/test/dao/test_RateDao.rb +5 -7
- data/test/dao/test_TradeResultDao.rb +1 -2
- data/test/migration/migration_tests.rb +10 -0
- data/test/migration/migrator1_2_0test_data/basic/out/M2NlOTA2ODEtZDdlNi00NWU1LWIwNDQtMjBmODY2ZGNkNzBj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/basic/out/MDVhYzcxMjYtMGFlMS00Mzk0LWEyNmUtYjVjZjgwNDA0ZmE2/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/basic/out/MzA1YTk0NDgtNzhjNi00NDk3LTk2NTktYzE1ZjBhNzdiYjNj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/basic/out/YjRkOTI1MzEtZTM4MS00YjQwLTg1ZTQtMWFmZDRlNDUwMzBm/56e75YuV5bmz5Z2H57ea/meta.yaml +9 -0
- data/test/migration/migrator1_2_0test_data/basic/props.yaml +85 -0
- data/test/migration/migrator1_2_0test_data/illegal_props/out/M2NlOTA2ODEtZDdlNi00NWU1LWIwNDQtMjBmODY2ZGNkNzBj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/illegal_props/out/MDVhYzcxMjYtMGFlMS00Mzk0LWEyNmUtYjVjZjgwNDA0ZmE2/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/illegal_props/out/MzA1YTk0NDgtNzhjNi00NDk3LTk2NTktYzE1ZjBhNzdiYjNj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/illegal_props/out/YjRkOTI1MzEtZTM4MS00YjQwLTg1ZTQtMWFmZDRlNDUwMzBm/56e75YuV5bmz5Z2H57ea/meta.yaml +9 -0
- data/test/migration/migrator1_2_0test_data/illegal_props/props.yaml +1 -0
- data/test/migration/migrator1_2_0test_data/no_outs/props.yaml +85 -0
- data/test/migration/migrator1_2_0test_data/no_props/out/M2NlOTA2ODEtZDdlNi00NWU1LWIwNDQtMjBmODY2ZGNkNzBj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/no_props/out/MDVhYzcxMjYtMGFlMS00Mzk0LWEyNmUtYjVjZjgwNDA0ZmE2/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/no_props/out/MzA1YTk0NDgtNzhjNi00NDk3LTk2NTktYzE1ZjBhNzdiYjNj/56e75YuV5bmz5Z2H57ea/meta.yaml +8 -0
- data/test/migration/migrator1_2_0test_data/no_props/out/YjRkOTI1MzEtZTM4MS00YjQwLTg1ZTQtMWFmZDRlNDUwMzBm/56e75YuV5bmz5Z2H57ea/meta.yaml +9 -0
- data/test/migration/test_Migrator.rb +1 -1
- data/test/migration/test_Migrator1_0_3.rb +1 -1
- data/test/migration/test_Migrator1_1_0.rb +1 -1
- data/test/migration/test_Migrator1_2_0.rb +94 -0
- data/test/plugin/embedded/test_SingleClickClient.rb +1 -2
- data/test/plugin/plugin_tests.rb +8 -0
- data/test/plugin/test_Loader.rb +1 -1
- data/test/shared/rate.csv +144 -0
- data/test/shared/shared_tests.rb +9 -0
- data/test/shared/test_Cross.rb +144 -0
- data/test/shared/test_PositionManager.rb +285 -0
- data/test/shared/test_Signal.rb +65 -0
- data/test/test_Output.rb +28 -21
- data/test/test_OutputManager.rb +162 -0
- data/test/test_Output_registry.rb +6 -17
- data/test/test_Process.rb +434 -222
- data/test/test_ProcessManager.rb +458 -101
- data/test/test_utils.rb +71 -8
- data/test/util/test_BlockToSession.rb +1 -2
- data/test/util/test_CSV.rb +1 -2
- data/test/util/test_SynchronizeInterceptor.rb +1 -2
- data/test/util/util_tests.rb +9 -0
- metadata +127 -47
- data/html/js/agent-editor-page.js +0 -440
- data/html/js/codepress/codepress.css +0 -21
- data/html/js/codepress/codepress.html +0 -35
- data/html/js/codepress/codepress.js +0 -138
- data/html/js/codepress/engines/gecko.js +0 -293
- data/html/js/codepress/engines/khtml.js +0 -0
- data/html/js/codepress/engines/msie.js +0 -304
- data/html/js/codepress/engines/older.js +0 -0
- data/html/js/codepress/engines/opera.js +0 -260
- data/html/js/codepress/images/line-numbers.gif +0 -0
- data/html/js/codepress/index.html +0 -443
- data/html/js/codepress/languages/asp.css +0 -71
- data/html/js/codepress/languages/asp.js +0 -117
- data/html/js/codepress/languages/autoit.css +0 -13
- data/html/js/codepress/languages/autoit.js +0 -32
- data/html/js/codepress/languages/csharp.css +0 -9
- data/html/js/codepress/languages/csharp.js +0 -25
- data/html/js/codepress/languages/css.css +0 -10
- data/html/js/codepress/languages/css.js +0 -23
- data/html/js/codepress/languages/generic.css +0 -9
- data/html/js/codepress/languages/generic.js +0 -25
- data/html/js/codepress/languages/html.css +0 -13
- data/html/js/codepress/languages/html.js +0 -59
- data/html/js/codepress/languages/java.css +0 -7
- data/html/js/codepress/languages/java.js +0 -24
- data/html/js/codepress/languages/javascript.css +0 -8
- data/html/js/codepress/languages/javascript.js +0 -30
- data/html/js/codepress/languages/perl.css +0 -11
- data/html/js/codepress/languages/perl.js +0 -27
- data/html/js/codepress/languages/php.css +0 -12
- data/html/js/codepress/languages/php.js +0 -61
- data/html/js/codepress/languages/ruby.css +0 -10
- data/html/js/codepress/languages/ruby.js +0 -26
- data/html/js/codepress/languages/sql.css +0 -10
- data/html/js/codepress/languages/sql.js +0 -30
- data/html/js/codepress/languages/text.css +0 -5
- data/html/js/codepress/languages/text.js +0 -9
- data/html/js/codepress/languages/vbscript.css +0 -71
- data/html/js/codepress/languages/vbscript.js +0 -117
- data/html/js/codepress/languages/xsl.css +0 -15
- data/html/js/codepress/languages/xsl.js +0 -103
- data/html/js/codepress/license.txt +0 -458
- data/html/js/edit_area/images/Thumbs.db +0 -0
- data/test/plugin/test_gem/a/lib/jiji_plugin_test.rb +0 -6
data/ChangeLog
CHANGED
@@ -1,7 +1,30 @@
|
|
1
1
|
|
2
|
+
2009-8-15 1.2.0
|
3
|
+
* エージェントエディタを一新
|
4
|
+
- 複数のエージェントや共有ライブラリをタブで同時に編集できるようになりました。
|
5
|
+
- エージェントや共有ライブラリをディレクトリで分類できるようになりました。
|
6
|
+
|
7
|
+
* 標準ライブラリの追加
|
8
|
+
標準添付の共有ライブラリとして、以下を追加。
|
9
|
+
- 移動平均などの各種シグナル算出クラス
|
10
|
+
- ロスカットやトレーリングストップを容易に実現するPositionManager
|
11
|
+
- クロスアップ、クロスダウンを判定するためのユーティリティ
|
12
|
+
|
13
|
+
* バックテストの再実行機能を追加
|
14
|
+
- バックテストを1クリックで再実行できるようになりました。
|
15
|
+
|
16
|
+
* グラフ出力の不具合修正
|
17
|
+
- エージェントを削除するとそのグラフも表示できなくなる問題を改修しました。
|
18
|
+
- この変更でリアルトレードでは古いグラフが蓄積されていくようになったため、
|
19
|
+
不要なグラフを破棄する機能も追加しました。
|
20
|
+
|
21
|
+
2009-8-8 1.1.4
|
22
|
+
* クリック証券デモ取引Webサービスの提供終了にあわせて、デモ取引接続プラグインを
|
23
|
+
無効化
|
24
|
+
|
2
25
|
2009-7-5 1.1.3
|
3
26
|
* クリック証券のデモ取引に接続する場合に、設定でプロキシを空のまま確定すると
|
4
|
-
|
27
|
+
接続エラーになる不具合を改修。
|
5
28
|
|
6
29
|
2009-6-29 1.1.2
|
7
30
|
* クリック証券プラグインを標準添付
|
data/README
CHANGED
File without changes
|
@@ -1,34 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
@
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@rates.
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
total += s.
|
30
|
-
total += s.
|
31
|
-
|
32
|
-
|
33
|
-
|
1
|
+
|
2
|
+
# 一定期間の移動平均を得る
|
3
|
+
class MovingAverage
|
4
|
+
def initialize( range=25 )
|
5
|
+
@rates = [] # レートを記録するバッファ
|
6
|
+
@range = range
|
7
|
+
end
|
8
|
+
|
9
|
+
def next_rate( rate )
|
10
|
+
# バッファのデータを更新
|
11
|
+
@rates.push rate
|
12
|
+
@rates.shift if @rates.length > @range
|
13
|
+
|
14
|
+
# バッファサイズが十分でなければ、nilを返す。
|
15
|
+
return nil if @rates.length != @range
|
16
|
+
|
17
|
+
# 移動平均を算出
|
18
|
+
return MovingAverage.get_moving_average(@rates)
|
19
|
+
end
|
20
|
+
|
21
|
+
# 前の結果(引数で指定した件数だけ記録。)
|
22
|
+
attr :prev, true
|
23
|
+
|
24
|
+
private
|
25
|
+
# 移動平均値を計算する。
|
26
|
+
def self.get_moving_average( rates )
|
27
|
+
total = 0
|
28
|
+
rates.each {|s|
|
29
|
+
total += s.end
|
30
|
+
total += s.max
|
31
|
+
total += s.min
|
32
|
+
}
|
33
|
+
return total / ( rates.length * 3 )
|
34
|
+
end
|
34
35
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
#===交差状態を判定するユーティリティ
|
3
|
+
#先行指標と遅行指標を受け取って、クロスアップ/クロスダウンを判定するユーティリティです。
|
4
|
+
#
|
5
|
+
# require 'cross'
|
6
|
+
#
|
7
|
+
# cross = Cross.new
|
8
|
+
#
|
9
|
+
# # 先行指標、遅行指標を受け取って状態を返す。
|
10
|
+
# # :cross .. クロスアップ、クロスダウン状態かどうかを返す。
|
11
|
+
# # - クロスアップ(:up)
|
12
|
+
# # - クロスダウン(:down)
|
13
|
+
# # - どちらでもない(:none)
|
14
|
+
# # :trend .. 現在の指標が上向きか下向きかを返す。
|
15
|
+
# # 「先行指標 <=> 遅行指標」した値。
|
16
|
+
# # trend >= 1なら上向き、trned <= -1なら下向き
|
17
|
+
# p cross.next_data( 100, 90 ) # {:trend=>1, :cross=>:none}
|
18
|
+
# p cross.next_data( 110, 100 ) # {:trend=>1, :cross=>:none}
|
19
|
+
# p cross.next_data( 100, 100 ) # {:trend=>0, :cross=>:none}
|
20
|
+
# p cross.next_data( 90, 100 ) # {:trend=>-1, :cross=>:down}
|
21
|
+
# p cross.next_data( 80, 90 ) # {:trend=>-1, :cross=>:none}
|
22
|
+
# p cross.next_data( 90, 90 ) # {:trend=>0, :cross=>:none}
|
23
|
+
# p cross.next_data( 100, 100 ) # {:trend=>0, :cross=>:none}
|
24
|
+
# p cross.next_data( 110, 100 ) # {:trend=>1, :cross=>:up}
|
25
|
+
#
|
26
|
+
class Cross
|
27
|
+
|
28
|
+
#コンストラクタ
|
29
|
+
def initialize
|
30
|
+
@cross_prev = nil
|
31
|
+
@cross = :none
|
32
|
+
@trend = 0
|
33
|
+
end
|
34
|
+
|
35
|
+
#===次の値を渡し状態を更新します。
|
36
|
+
#fast:: 先行指標
|
37
|
+
#lazy:: 遅行指標
|
38
|
+
def next_data( fast, lazy )
|
39
|
+
return unless fast && lazy
|
40
|
+
# 交差状態を算出
|
41
|
+
@trend = fast <=> lazy
|
42
|
+
if @cross_prev && @trend != @cross_prev && @trend != 0
|
43
|
+
@cross = @trend > @cross_prev ? :up : :down
|
44
|
+
else
|
45
|
+
@cross = :none
|
46
|
+
end
|
47
|
+
@cross_prev = @trend
|
48
|
+
return {:cross=>@cross,:trend=>@trend}
|
49
|
+
end
|
50
|
+
|
51
|
+
#===クロスアップ状態かどうか判定します。
|
52
|
+
#戻り値:: 「先行指標 < 遅行指標」 から 「先行指標 > 遅行指標」 になったらtrue
|
53
|
+
def cross_up?
|
54
|
+
@cross == :up
|
55
|
+
end
|
56
|
+
#===クロスダウン状態かどうか判定します。
|
57
|
+
#戻り値:: 「先行指標 > 遅行指標」 から 「先行指標 < 遅行指標」 になったらtrue
|
58
|
+
def cross_down?
|
59
|
+
@cross == :down
|
60
|
+
end
|
61
|
+
#===上昇トレンド中かどうか判定します。
|
62
|
+
#戻り値:: 「先行指標 > 遅行指標」 ならtrue
|
63
|
+
def up?
|
64
|
+
@trend > 0
|
65
|
+
end
|
66
|
+
#===下降トレンド中かどうか判定します。
|
67
|
+
#戻り値:: 「先行指標 < 遅行指標」 ならtrue
|
68
|
+
def down?
|
69
|
+
@trend < 0
|
70
|
+
end
|
71
|
+
|
72
|
+
#交差状態( :up, :down, :none )
|
73
|
+
attr_reader :cross
|
74
|
+
#トレンド ( 直近の falst <=> lazy 値。)
|
75
|
+
attr_reader :trend
|
76
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
|
2
|
+
#===ポジションマネージャ
|
3
|
+
#以下の機能を提供するユーティリティクラスです。
|
4
|
+
#- 条件にマッチするポジションを探す。
|
5
|
+
#- すべてのor条件にマッチするポジションを決済する。
|
6
|
+
#- 指定したポジションを損切りorトレーリングストップで決済する。
|
7
|
+
class PositionManager
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
#====コンストラクタ
|
11
|
+
#operator:: オペレータ
|
12
|
+
def initialize( operator )
|
13
|
+
raise "illegal argument." unless operator
|
14
|
+
@operator = operator
|
15
|
+
@marked = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
#====ポジションを列挙します。
|
19
|
+
def each( &block )
|
20
|
+
@operator.positions.each_pair {|k,v|
|
21
|
+
yield v
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
#====条件にマッチするポジションを決済します。
|
26
|
+
#&block:: 決済するポジションを判定するブロック。JIJI::Positionが引数として渡され、trueが返された場合決済されます。
|
27
|
+
def commit_by
|
28
|
+
each {|p|
|
29
|
+
@operator.commit( p ) if yield p
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
#====すべてのポジションを決済します。
|
34
|
+
def commit_all
|
35
|
+
commit_by{|p| true }
|
36
|
+
end
|
37
|
+
|
38
|
+
#====現在保有しているポジションの損益合計を取得します。
|
39
|
+
#※決済済みポジションの損益は含まれません。
|
40
|
+
#戻り値:: 現在保有しているポジションの損益合計
|
41
|
+
def total_profit_or_loss
|
42
|
+
inject(0.0) {|t, p|
|
43
|
+
t += p.profit_or_loss
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
#====ポジションに損切りロジックを登録します。
|
48
|
+
#損切りロジックが登録されたポジションはcheckが実行される度に損益がチェックされ、
|
49
|
+
#PositionManager::StopStrategy.close?がtrueになれば決済されます。
|
50
|
+
#1つのポジションに対して複数のロジックを設定可能。いずれかのロジックがtrueを返せば損切りされます。
|
51
|
+
#position_id:: ポジションID
|
52
|
+
#stop_strategy:: 損切りルール(PositionManager::StopStrategy)
|
53
|
+
def register( position_id, stop_strategy )
|
54
|
+
@marked[position_id] ||= []
|
55
|
+
@marked[position_id] << stop_strategy
|
56
|
+
end
|
57
|
+
|
58
|
+
#====ポジションをロスカットの対象としてマークします。
|
59
|
+
#マークされたポジションはcheckが実行される度に損益がチェックされ、
|
60
|
+
#損失がdissipationで設定した値以下になっていれば決済されます。
|
61
|
+
#
|
62
|
+
#position_id:: ポジションID
|
63
|
+
#dissipation:: 許容しうる損失
|
64
|
+
def register_loss_cut( position_id, dissipation )
|
65
|
+
register(position_id,LossCut.new( dissipation ))
|
66
|
+
end
|
67
|
+
|
68
|
+
#====ポジションをトレーリングストップの対象としてマークします。
|
69
|
+
#マークされたポジションはcheckが実行される度に損益がチェックされ、
|
70
|
+
#「今までの最高損益-現在の損益」がdissipationで設定した値以下になっていれば決済されます。
|
71
|
+
#
|
72
|
+
#position_id:: ポジションID
|
73
|
+
#dissipation:: 許容しうる損失
|
74
|
+
def register_trailing_stop( position_id, dissipation )
|
75
|
+
register(position_id,TrailingStop.new( dissipation ))
|
76
|
+
end
|
77
|
+
|
78
|
+
#====ポジションに損切りロジックが登録されているかどうか評価します。
|
79
|
+
#position_id:: ポジションID
|
80
|
+
#return:: 損切りの対象であればtrue
|
81
|
+
def registered?( position_id )
|
82
|
+
@marked.key?(position_id)
|
83
|
+
end
|
84
|
+
|
85
|
+
#====ポジションに登録されている損切りロジックの一覧を取得します。
|
86
|
+
#position_id:: ポジションID
|
87
|
+
#return:: ポジションに登録されている損切りロジックの配列
|
88
|
+
def get_registered_strategy( position_id )
|
89
|
+
@marked[position_id] || []
|
90
|
+
end
|
91
|
+
|
92
|
+
#====ポジションに登録された損切りロジックを解除します。
|
93
|
+
#position_id:: ポジションID
|
94
|
+
#strategy:: 削除する損切りロジック
|
95
|
+
def unregister(position_id, strategy)
|
96
|
+
list = get_registered_strategy(position_id)
|
97
|
+
list.delete(strategy)
|
98
|
+
end
|
99
|
+
|
100
|
+
#====ポジションに登録された損切りロジックを全て解除します。
|
101
|
+
#position_id:: ポジションID
|
102
|
+
def unregister_all(position_id)
|
103
|
+
@marked.delete( position_id )
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
#====監視対象のポジションが閾値を越えていないかチェックし、必要があれば決済します。
|
108
|
+
#定期的に実行してください。
|
109
|
+
#戻り値:: 決済したポジションの配列
|
110
|
+
def check
|
111
|
+
commited = []
|
112
|
+
@marked.each_pair {|k,v|
|
113
|
+
p = @operator.positions[k]
|
114
|
+
if !p || p.state != JIJI::Position::STATE_START
|
115
|
+
@marked.delete p.position_id
|
116
|
+
else
|
117
|
+
v.each {|strategy|
|
118
|
+
next unless strategy.close?(p)
|
119
|
+
@operator.commit( p )
|
120
|
+
commited << p
|
121
|
+
unregister_all( p.position_id )
|
122
|
+
break
|
123
|
+
}
|
124
|
+
end
|
125
|
+
}
|
126
|
+
commited
|
127
|
+
end
|
128
|
+
|
129
|
+
#===手じまい戦略
|
130
|
+
module StopStrategy
|
131
|
+
#====決済すべきか評価する。
|
132
|
+
#position:: ポジション(JIJI::Position)
|
133
|
+
def close?(position)
|
134
|
+
return false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
#===トレーリングストップ
|
138
|
+
class TrailingStop
|
139
|
+
include StopStrategy
|
140
|
+
def initialize( dissipation )
|
141
|
+
@dissipation=dissipation
|
142
|
+
end
|
143
|
+
def close?(position)
|
144
|
+
@max=0 if !@max
|
145
|
+
result = (@max - position.profit_or_loss)*-1 <= @dissipation
|
146
|
+
@max = [position.profit_or_loss, @max].max
|
147
|
+
return result
|
148
|
+
end
|
149
|
+
end
|
150
|
+
#===ロスカット
|
151
|
+
class LossCut
|
152
|
+
include StopStrategy
|
153
|
+
def initialize( dissipation )
|
154
|
+
@dissipation=dissipation
|
155
|
+
end
|
156
|
+
def close?(position)
|
157
|
+
position.profit_or_loss <= @dissipation
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,347 @@
|
|
1
|
+
|
2
|
+
module Signal
|
3
|
+
|
4
|
+
#===一定期間のレートデータを元に値を算出するシグナルの基底クラス
|
5
|
+
class RangeSignal
|
6
|
+
include Signal
|
7
|
+
#====コンストラクタ
|
8
|
+
#range:: 集計期間
|
9
|
+
def initialize( range=25 )
|
10
|
+
@datas = [] # レートを記録するバッファ
|
11
|
+
@range = range
|
12
|
+
end
|
13
|
+
#====次のデータを受け取って指標を返します。
|
14
|
+
#data:: 次のデータ
|
15
|
+
#戻り値:: 指標。十分なデータが蓄積されていない場合nil
|
16
|
+
def next_data( data )
|
17
|
+
# バッファのデータを更新
|
18
|
+
@datas.push data
|
19
|
+
@datas.shift if @datas.length > @range
|
20
|
+
|
21
|
+
# バッファサイズが十分でなければ、nilを返す。
|
22
|
+
return nil if @datas.length != @range
|
23
|
+
|
24
|
+
# 算出
|
25
|
+
return calculate(@datas)
|
26
|
+
end
|
27
|
+
#
|
28
|
+
def calculate(datas); end #:nodoc:
|
29
|
+
#集計期間
|
30
|
+
attr_reader :range
|
31
|
+
end
|
32
|
+
|
33
|
+
#===移動平均
|
34
|
+
class MovingAverage < RangeSignal
|
35
|
+
def calculate(datas) #:nodoc:
|
36
|
+
ma( datas )
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
#===加重移動平均
|
41
|
+
class WeightedMovingAverage < RangeSignal
|
42
|
+
def calculate(datas) #:nodoc:
|
43
|
+
wma( datas )
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#===指数移動平均
|
48
|
+
class ExponentialMovingAverage < RangeSignal
|
49
|
+
#====コンストラクタ
|
50
|
+
#range:: 集計期間
|
51
|
+
#smoothing_coefficient:: 平滑化係数
|
52
|
+
def initialize( range=25, smoothing_coefficient=0.1 )
|
53
|
+
super(range)
|
54
|
+
@sc = smoothing_coefficient
|
55
|
+
end
|
56
|
+
def calculate(datas) #:nodoc:
|
57
|
+
ema( datas, @sc )
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
#===ボリンジャーバンド
|
62
|
+
class BollingerBands < RangeSignal
|
63
|
+
#====コンストラクタ
|
64
|
+
#range:: 集計期間
|
65
|
+
#pivot:: ピボット
|
66
|
+
def initialize( range=25, pivot=[0,1,2], &block )
|
67
|
+
super(range)
|
68
|
+
@pivot = pivot
|
69
|
+
@block = block
|
70
|
+
end
|
71
|
+
def calculate(datas) #:nodoc:
|
72
|
+
bollinger_bands( datas, @pivot, &@block )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
#===傾き
|
77
|
+
class Momentum < RangeSignal
|
78
|
+
def calculate(datas) #:nodoc:
|
79
|
+
momentum( datas )
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#===傾き(最小二乗法を利用)
|
84
|
+
class Vector < RangeSignal
|
85
|
+
def calculate(datas)
|
86
|
+
vector( datas )
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
#===MACD
|
91
|
+
class MACD < RangeSignal
|
92
|
+
#====コンストラクタ
|
93
|
+
#short_range:: 短期EMAの集計期間
|
94
|
+
#long_range:: 長期EMAの集計期間
|
95
|
+
#signal_range:: シグナルの集計期間
|
96
|
+
#smoothing_coefficient:: 平滑化係数
|
97
|
+
def initialize( short_range=12, long_range=26,
|
98
|
+
signal_range=9, smoothing_coefficient=0.1 )
|
99
|
+
raise "illegal arguments." if short_range > long_range
|
100
|
+
super(long_range)
|
101
|
+
@short_range = short_range
|
102
|
+
@smoothing_coefficient = smoothing_coefficient
|
103
|
+
@signal = ExponentialMovingAverage.new(
|
104
|
+
signal_range, smoothing_coefficient )
|
105
|
+
end
|
106
|
+
def next_data( data ) #:nodoc:
|
107
|
+
macd = super
|
108
|
+
return nil unless macd
|
109
|
+
signal = @signal.next_data( macd )
|
110
|
+
return nil unless signal
|
111
|
+
return { :macd=>macd, :signal=>signal }
|
112
|
+
end
|
113
|
+
def calculate(datas) #:nodoc:
|
114
|
+
macd( datas, @short_range, range, @smoothing_coefficient )
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#===RSI
|
119
|
+
class RSI < RangeSignal
|
120
|
+
#====コンストラクタ
|
121
|
+
#range:: 集計期間
|
122
|
+
def initialize( range=14 )
|
123
|
+
super(range)
|
124
|
+
end
|
125
|
+
def calculate(datas) #:nodoc:
|
126
|
+
rsi( datas )
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
#===DMI
|
131
|
+
class DMI < RangeSignal
|
132
|
+
#====コンストラクタ
|
133
|
+
#range:: 集計期間
|
134
|
+
def initialize( range=14 )
|
135
|
+
super(range)
|
136
|
+
@dxs = []
|
137
|
+
end
|
138
|
+
def calculate(datas) #:nodoc:
|
139
|
+
dmi = dmi( datas )
|
140
|
+
return nil unless dmi
|
141
|
+
@dxs.push dmi[:dx]
|
142
|
+
@dxs.shift if @dxs.length > range
|
143
|
+
return nil if @dxs.length != range
|
144
|
+
dmi[:adx] = ma( @dxs )
|
145
|
+
return dmi
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#===ROC
|
150
|
+
class ROC < RangeSignal
|
151
|
+
#====コンストラクタ
|
152
|
+
#range:: 集計期間
|
153
|
+
def initialize( range=14 )
|
154
|
+
super(range)
|
155
|
+
end
|
156
|
+
def calculate(datas) #:nodoc:
|
157
|
+
roc( datas )
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
module_function
|
162
|
+
|
163
|
+
#===移動平均値を計算します。
|
164
|
+
#datas:: 値の配列。
|
165
|
+
#戻り値:: 移動平均値
|
166
|
+
def ma( datas )
|
167
|
+
total = datas.inject {|t,s|
|
168
|
+
t += s; t
|
169
|
+
}
|
170
|
+
return total / datas.length
|
171
|
+
end
|
172
|
+
|
173
|
+
#===加重移動平均値を計算します。
|
174
|
+
#datas:: 値の配列。
|
175
|
+
#戻り値:: 加重移動平均値
|
176
|
+
def wma( datas )
|
177
|
+
weight = 1
|
178
|
+
total = datas.inject(0.0) {|t,s|
|
179
|
+
t += s * weight
|
180
|
+
weight += 1
|
181
|
+
t
|
182
|
+
}
|
183
|
+
return total / ( datas.length * (datas.length+1) /2 )
|
184
|
+
end
|
185
|
+
|
186
|
+
#===指数移動平均値を計算します。
|
187
|
+
#datas:: 値の配列。
|
188
|
+
#smoothing_coefficient:: 平滑化係数
|
189
|
+
#戻り値:: 加重移動平均値
|
190
|
+
def ema( datas, smoothing_coefficient=0.1 )
|
191
|
+
datas[1..-1].inject( datas[0] ) {|t,s|
|
192
|
+
t + smoothing_coefficient * (s - t)
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
#===ボリンジャーバンドを計算します。
|
198
|
+
#
|
199
|
+
# +2σ=移動平均+標準偏差×2
|
200
|
+
# +σ=移動平均+標準偏差
|
201
|
+
# -σ=移動平均-標準偏差
|
202
|
+
# -2σ=移動平均-標準偏差×2
|
203
|
+
# 標準偏差=√((各値-値の期間中平均値)の2乗を期間分全部加えたもの)/ 期間
|
204
|
+
# (√は式全体にかかる)
|
205
|
+
#
|
206
|
+
#datas:: 値の配列
|
207
|
+
#pivot:: 標準偏差の倍数。初期値[0,1,2]
|
208
|
+
#block:: 移動平均を算出するロジック。指定がなければ移動平均を使う。
|
209
|
+
#戻り値:: ボリンジャーバンドの各値の配列。例) [+2σ, +1σ, TP, -1σ, -2σ]
|
210
|
+
#
|
211
|
+
def bollinger_bands( datas, pivot=[0,1,2], &block )
|
212
|
+
ma = block_given? ? yield( datas ) : ma( datas )
|
213
|
+
total = datas.inject(0.0) {|t,s|
|
214
|
+
t+= ( s - ma ) ** 2
|
215
|
+
t
|
216
|
+
}
|
217
|
+
sd = Math.sqrt(total / datas.length)
|
218
|
+
res = []
|
219
|
+
pivot.each { |r|
|
220
|
+
res.unshift( ma + sd * r )
|
221
|
+
res.push( ma + sd * r * -1 ) if r != 0
|
222
|
+
}
|
223
|
+
return res
|
224
|
+
end
|
225
|
+
|
226
|
+
#===一定期間の値の傾きを計算します。
|
227
|
+
#datas:: 値の配列
|
228
|
+
#戻り値:: 傾き。0より大きければ上向き。小さければ下向き。
|
229
|
+
def momentum( datas )
|
230
|
+
(datas.last - datas.first) / datas.length
|
231
|
+
end
|
232
|
+
|
233
|
+
#===最小二乗法で、一定期間の値の傾きを計算します。
|
234
|
+
#datas:: 値の配列
|
235
|
+
#戻り値:: 傾き。0より大きければ上向き。小さければ下向き。
|
236
|
+
def vector( datas )
|
237
|
+
# 最小二乗法を使う。
|
238
|
+
total = {:x=>0.0,:y=>0.0,:xx=>0.0,:xy=>0.0,:yy=>0.0}
|
239
|
+
datas.each_index {|i|
|
240
|
+
total[:x] += i
|
241
|
+
total[:y] += datas[i]
|
242
|
+
total[:xx] += i*i
|
243
|
+
total[:xy] += i*datas[i]
|
244
|
+
total[:yy] += datas[i] * datas[i]
|
245
|
+
}
|
246
|
+
n = datas.length
|
247
|
+
d = total[:xy]
|
248
|
+
c = total[:y]
|
249
|
+
e = total[:x]
|
250
|
+
b = total[:xx]
|
251
|
+
return (n*d - c*e) / (n*b - e*e)
|
252
|
+
end
|
253
|
+
|
254
|
+
#===MACDを計算します。
|
255
|
+
#MACD = 短期(short_range日)の指数移動平均 - 長期(long_range日)の指数移動平均
|
256
|
+
#datas:: 値の配列
|
257
|
+
#smoothing_coefficient:: 平滑化係数
|
258
|
+
#戻り値:: macd値
|
259
|
+
def macd( datas, short_range, long_range, smoothing_coefficient )
|
260
|
+
ema( datas[ short_range*-1 .. -1], smoothing_coefficient ) \
|
261
|
+
- ema( datas[ long_range*-1 .. -1], smoothing_coefficient )
|
262
|
+
end
|
263
|
+
|
264
|
+
#===RSIを計算します。
|
265
|
+
#RSI = n日間の値上がり幅合計 / (n日間の値上がり幅合計 + n日間の値下がり幅合計) * 100
|
266
|
+
#nとして、14や9を使うのが、一般的。30以下では売られすぎ70以上では買われすぎの水準。
|
267
|
+
#
|
268
|
+
#datas:: 値の配列
|
269
|
+
#戻り値:: RSI値
|
270
|
+
def rsi( datas )
|
271
|
+
prev = nil
|
272
|
+
tmp = datas.inject( [0.0,0.0] ) {|r,i|
|
273
|
+
r[ i > prev ? 0 : 1 ] += (i - prev).abs if prev
|
274
|
+
prev = i
|
275
|
+
r
|
276
|
+
}
|
277
|
+
(tmp[0] + tmp[1] ) == 0 ? 0.0 : tmp[0] / (tmp[0] + tmp[1]) * 100
|
278
|
+
end
|
279
|
+
|
280
|
+
#===DMIを計算します。
|
281
|
+
#
|
282
|
+
# 高値更新 ... 前日高値より当日高値が高かった時その差
|
283
|
+
# 安値更新 ... 前日安値より当日安値が安かった時その差
|
284
|
+
# DM ... 高値更新が安値更新より大きかった時高値更新の値。逆の場合は0
|
285
|
+
# DM ... 安値更新が高値更新より大きかった時安値更新の値。逆の場合は0
|
286
|
+
# TR ... 次の3つの中で一番大きいもの
|
287
|
+
# 当日高値-当日安値
|
288
|
+
# 当日高値-前日終値
|
289
|
+
# 前日終値-当日安値
|
290
|
+
# AV(+DM) ... +DMのn日間移動平均値
|
291
|
+
# AV(-DM) ... -DMのn日間移動平均値
|
292
|
+
# AV(TR) ... TRのn日間移動平均値
|
293
|
+
# +DI ... AV(+DM)/AV(TR)
|
294
|
+
# -DI ... AV(-DM)/AV(TR)
|
295
|
+
# DX ... (+DIと-DIの差額) / (+DIと-DIの合計)
|
296
|
+
# ADX ... DXのn日平均値
|
297
|
+
#
|
298
|
+
#datas:: 値の配列(4本値を指定すること!)
|
299
|
+
#戻り値:: {:pdi=pdi, :mdi=mdi, :dx=dx }
|
300
|
+
def dmi( datas )
|
301
|
+
prev = nil
|
302
|
+
tmp = datas.inject( [[],[],[]] ) {|r,i|
|
303
|
+
if prev
|
304
|
+
dm = _dmi( i, prev )
|
305
|
+
r[0] << dm[0] # TR
|
306
|
+
r[1] << dm[1] # +DM
|
307
|
+
r[2] << dm[2] # -DM
|
308
|
+
end
|
309
|
+
prev = i
|
310
|
+
r
|
311
|
+
}
|
312
|
+
atr = ma( tmp[0] )
|
313
|
+
pdi = ma( tmp[1] ) / atr * 100
|
314
|
+
mdi = ma( tmp[2] ) / atr * 100
|
315
|
+
dx = ( pdi-mdi ).abs / ( pdi+mdi ) * 100
|
316
|
+
return {:pdi=>pdi, :mdi=>mdi, :dx=>dx }
|
317
|
+
end
|
318
|
+
|
319
|
+
#TR,+DM,-DMを計算します。
|
320
|
+
#戻り値:: [ tr, +DM, -DM ]
|
321
|
+
def _dmi( rate, rate_prev ) #:nodoc:
|
322
|
+
pdm = rate.max > rate_prev.max ? rate.max - rate_prev.max : 0
|
323
|
+
mdm = rate.min < rate_prev.min ? rate_prev.min - rate.min : 0
|
324
|
+
|
325
|
+
if ( pdm > mdm )
|
326
|
+
mdm = 0
|
327
|
+
elsif ( pdm < mdm )
|
328
|
+
pdm = 0
|
329
|
+
end
|
330
|
+
|
331
|
+
a = rate.max - rate.min
|
332
|
+
b = rate.max - rate_prev.end
|
333
|
+
c = rate_prev.end - rate.min
|
334
|
+
tr = [a,b,c].max
|
335
|
+
|
336
|
+
return [tr, pdm, mdm]
|
337
|
+
end
|
338
|
+
|
339
|
+
#===ROCを計算します。
|
340
|
+
#Rate of Change。変化率。正なら上げトレンド、負なら下げトレンド。
|
341
|
+
#
|
342
|
+
#datas:: 値の配列
|
343
|
+
#戻り値:: 値
|
344
|
+
def roc( datas )
|
345
|
+
(datas.first - datas.last) / datas.last * 100
|
346
|
+
end
|
347
|
+
end
|