★★★★ 前回記事を2011/5/22 12:26に追加修正しました ★★★★★
そして、次のネタに悩みつつ、「FXシステムトレード初心者奮闘記」の「MT4用EA開発時代」はどこかに向かっていくのでした。。
さて前回は、MT4用EAでロット数計算のプログラミング方法に関して書きました。今回は、注文/価格計算/ロット数計算の各論が終ったので、それらを統合して一つの処理の流れを記載するMT4用EAのstart()内の流れについて書いてみたいと思います。
まずはstart()関数内の基本的な流れについてから。
#なので、以下の流れでは、今まで検討してきた運用性とか障害対応、リスク回避等の内容は含まれていないシンプルなもの。
【基本的なstart()関数内の流れ】
----------------------------
1.init()完了確認
ヘルプをよく読むと、init()関数が終っていなくても、start()関数が開始される可能性がある とのこと。なので、外部変数でinit()関数が終ったかどうかのフラグFALSEによる初期化で定義。
init()処理完了時に、該当フラグをTRUEにする様にしておく。
start()開始時は、このフラグがFALSEであればリターンする様にしておく。
2.状態確認
init()処理完了時に、該当フラグをTRUEにする様にしておく。
start()開始時は、このフラグがFALSEであればリターンする様にしておく。
2.状態確認
・IsStopped()がTRUEであれば、終了する。
→ これは、EA停止時の2.5秒ルールにすぐに対応できる様にする為。
処理続行してしまうと、その後の処理でサーバ側処理遅延起因で、
2.5秒を超過してしまう可能性があるので最初に確認。
・IsConnected()がFALSEであれば、Sleep()&RefreshRates()リトライを実施
→ 本当に必要か正直疑問。この関数が呼ばれてるのであれば、ティックデータ受信
しているという事なので、接続もされているはず。削除するか、IsTradeAllowed()の
後ろに移動する。移動させる理由は、IsTradeAllowed()がコンテキスト・ビジー
で失敗した場合、スリープ&リトライするので、時間がかかってしまう。
スリープしている間に、セッションが切れてしまうかもしれないので。
もし、IsTradeAllowed()内で、IsConnected()相当のチェックをしているのであれば、
存在意義は全くない。
・IsTradeAllowed()がFALSEであれば、Sleep()&RefreshRates()&リトライを実施
→ 必要性は薄いが、「Expert Advisors」→「Properties」→「全般」で、
「Allow live trading」の設定漏れは検出できる。
3.保有中ポジション情報の取得
現在、チャートに結びついているEAのポジションをOrderSelect()する。
方式は、OrderSelect()で通貨ペアとMAGICが一致するか、OrdersTotal()回ループ
するまで続ける。見つからなければ、保有中ポジションなしと判断。
見つかれば、OrderSelect()済みとなり、OrderOpenPrice()等のOrderSelect()後で
ないと使えない関数呼び出しが可能になる。
→ 異なるタイムフレームで同じ通貨ペア/MAGICで動かす場合は、識別する際に
もう一工夫必要。同じEAでもMAGICを別番号にするのが素直かも。
なので、MAGICはプロパティ化した方がいいと思う。
4.ポジション保有中であれば、決済すべきかどうかを判定し、決済要であれば、
保有中該当ポジションの決済(OrderClose)する。
5.まだ保有中ポジションがある場合に、トレーリングする
売買ルール上、保有中ポジションの情報変更(OrderModify)する場合は、このタイミング
で実施する。
6.発注可否判定
・保有中のポジションが無い事を改めて確認
同一のEA/通貨ペアで複数ポジションを持たないという原則があれば、
ここで改めて確認する。念のための確認ではあるが、上記「3.」で決済失敗時の
ハンドリングロジックにミスがあった場合の、ガード的な役割。
ハンドリングロジックにミスがあった場合の、ガード的な役割。
・前回発注したバーと同じバーであれば発注しない様にする
発注ルール次第だけど、あるバーで発注して、そのバー内でストップロスとかで
引っかかってしまうと、また同じバーで発注してしまう事に。
そうなると、1本のバーで、発注→ストップロスを繰り返してしまう可能性が
出てくるので、危険回避のため、この様なロジックを設ける事に。
7.ティックデータの最新化
保有ポジションがある状態で、start()関数が開始された場合、ここに来るまでに
次のティックデータが来ている可能性が高くなる。この後の処理で、発注に向けた
各種計算をすることを考えると、一旦ここでRefreshRates()しておいた方がいいと
思うので、入れてみた。
8.発注処理
発注要否判定と、発注情報(価格、ロット数等)の計算、発注処理を行う
-------------------------------------
以上が、start()関数の大まかな流れ。
じゃあ次は、共通部品としてはどうする予定なのかという事を記載してみた。以前の記事の絵にも同等の流れを書いているけど、もう少し意図を説明したいのと、見直しも発生したので、それも含めて書いて見ます。
まずは、「共通部品の関数間の関係」の最新版。
決して記事のカサ増しが目的ではありません。。。
【共通部品の関数間の関係】
---------------------------------
※小さくて文字が見えないので画像クリックして見てください。
※小さくて文字が見えないので画像クリックして見てください。
---------------------------------
左側にある「start()」関数部分で、前述したstart()関数の流れに追加した部分について、その内容と意図を書いてみた。
【共通部品固有のstart()関数内処理について】
---------------------------------
※以下の番号は、上記図のstart()のハコの中の番号
2.大域変数読み込み指示があれば、大域変数を読み込み
これは、デモ口座でEAを動かしてて必要性を思いついた事。
手動で大域変数データ補正による問題対処が可能になる。
ポジション保有した後にバグが発覚して、しかも保存している大域変数の内容が
不正な値になってしまった場合、補正して強制的に読み込める様にしておかないと、
間違えた情報のまま決済するまで待つか、手動決済が必要になってしまうため。
大域変数読み込み指示用の大域変数キーの値が0以外であれば、大域変数を
読み込み直す処理を入れることにした。
5.保有していたはずのポジションが決済されていたかチェック
保有ポジション決済後の処理として、戦略ストップの判定をしたり、ログを出力したり、
大域変数を削除したりする為。
保有中ポジションのチケット番号を大域変数に格納しておかないと、ポジション保有中
にMT4を停止し、起動する前にSL/TP等による決済がされていた時に、上記決済時
処理が動作しない。
処理が動作しない。
6.各種EA固有コールバック関数呼出し
これらは、売買ルールによっては必要になるかもしれないので追加しただけ。
売買ルールによっては、ポジション保有中でなくても何かのデータを蓄積していったり、
ペンディング中オーダ約定時の情報を元に決済する必要があったりするかもしれないので。
8.今回ポジション決済となっていた場合
・トレードログ出力
「トレーディング・プラン」で決めたシステム停止要否判定するのに
「トレーディング・プラン」で決めたシステム停止要否判定するのに
必要な情報の出力処理は、ポジション決済時にするため。
・大域変数の削除
大域変数はMT4を再起動しても消えないので、できるだけゴミを残さない様にしたい。
同じ通貨ペア/MAGICに対応する大域変数を削除する。
・戦略ストップ判定
ドローダウン率がプロパティで指定した閾値以上になれば、「戦略ストップ状態」に
状態変更され、MT4を再起動しても新規発注しない様になる。
また、ドローダウン率が前述の閾値よりちょっと前のプロパティ化された水準に達
した場合、「戦略ストップ警告状態」に変更してメール通知。
「戦略ストップ警告状態」の場合は、新規発注停止はしない。
その後の最大ドローダウン時の残高から、一定率以上に残高が増加すれば、
「戦略ストップ警告状態」を解除し、その旨をメール通知。
わざわざこんな事をしているのは、「戦略ストップ警告状態」となる閾値前後で
口座残高が推移した場合に、何回も警告メールが発出されてしまうのを防止するため。
10.発注可否判定
・致命的な異常を検出していた場合
これはバグ起因等の想定外の異常を検出しているということは、これ以上発注した場合に
被害が拡大する危険性があるので、新規発注を禁止することに。
この状態は、MT4再起動で解除される様にした。
場合によっては、OSやHWの不安定性/故障に起因するケースも考えられるので、
再起動による対応という可能性もある。
この場合、「新規発注禁止状態」をMT4再起動後も有効にしたとすると、一つ一つ
解除しなければならないが、その解除作業が漏れてしまう可能性があるし、面倒。
原因が、プログラムミスの場合は、後述の「計画新規発注停止指示」をする運用に。
・保有ポジションがあったのが、なくなっていればリターンする
これは【基本的なstart()関数内の流れ】の「5.発注可否判定」の中で、
保有ポジション有無確認した結果、その直前までポジション保有していると
認識していたのが、処理中にSL/TPによる決済によりポジション無しに
なってしまった場合に、上記「8.今回ポジション決済となっていた場合」が動作
せずに、次のオーダ発注になってしまう可能性があるため。
・新規発注停止指示があった場合
EAを計画的に停止(トレーディング・プランによるシステム停止等を想定)させる
場合、MT4で計画停止用の大域変数に「0」以外を設定することにより、
保有中ポジションが決済されるまでは従来動作させ、その後は新規発注させない様に
するため。
11.プロパティが変更されていた場合、内部変数に新プロパティ値を適用
この処理により、ポジション保有中のプロパティ変更後に、MT4再起動しても、
保有中ポジションは旧パラメータで決済まで動作し、決済後からは新たなパラメータ
に自動的に切り替わる様になる。
この処理での動きは、定期的な最適化パラメータを適用する際、保有中ポジションに
適用してしまうと不都合がある場合に、プロパティ値を、対応する変数に適用して、
さらに対応する大域変数に保存する。
---------------------------------
ちなみに、ずーっと、書き忘れていたことが。
それは、「警告音」
【警告音について】
---------------------------
今回、VPS利用をやめMT4を動作させるPCを自宅のノートPCにすることにした。
なので、自宅で動いている事を利用して、異常時はアラーム音を鳴らす事に。
自宅にいる時に、異常を直ぐに気付ける様にするため。
●アラーム音を鳴らすタイミング
1.エラー検出時で、[[WARNING]]/[[CRITICAL]]レベルのエラーを検出したとき。
2.致命的な異常検出による「新規発注禁止状態」の場合に一定間隔(数秒単位)
→ デモ口座上で動かしてるEAで一回この状態になったが、結構あせった(笑)
---------------------------
こんな長い文章、最後まで読んでくれるのだろうか。。
誰か設計バグを
コメントしてくれたら
嬉しいなぁ。。。
そして、次のネタに悩みつつ、「FXシステムトレード初心者奮闘記」の「MT4用EA開発時代」はどこかに向かっていくのでした。。
#ブログ書くためにソース眺めてたらバグ発見した。。
0 件のコメント:
コメントを投稿