Simulink:Expert Advisors開発者へのガイド
はじめに
Matlabの大きな可能性に言及した記事は複数あります。正確に言うと、このソフトウェアがプログラマがExpert Advisorを作成するのに使うツールを拡げる方法と申しましょうか。本稿では、Simulinkというそういう力強いmatlabパッケージの動作について述べていきます。
トレーダーが自動化トレーディングシステムを開発するもう一つの方法を提供したいと思うのです。トレーダーが直面する問題の複雑性ゆえにこの手法を始めようと思いました - 自動化トレーディングシステムの作成、確認、検証においてです。私はプロのプログラマではありません。そのため、自動化トレーディングシステム開発をする際、「シンプルから複雑へ」という原則は私にとって重要なものです。では私にとってシンプルとは正確にどういうことを言うのでしょうか?まず、これはシステム作成プロセスの視覚化、そしてそれが機能するロジックです。また、手書きコードを最小限に抑えることです。この期待はMATLAB製品としてよく知られるSimulink® パッケージの機能においてまさに一貫性があります。それは数学的計算を可視化する手段として世界的な先駆けです。
本稿では、Matlabパッケージを基にトレーディングシステムを作成し検証することを目指しています。そしてIMetaTrader 5用のExpert Advisorを書いていきます。その上、バックテスト用の履歴データはすべてMetaTrader 5から使用されます。
用語的混乱を避けるため、Simulinikで機能するトレーディングシステムを広い意味の言葉でMTSと呼び、MQL5で機能するものを単純にExpert Advisorと呼ぶことにします。
1. Simulink とStateflowの基本
特定の処理に移る前に理論的に最低限の形式をいくつかご紹介する必要があると思います。
MATLABの一部分であるSimulink®パッケージの助けを借りて、ユーザーは動的システムのモデル化、シミュレーション、分析を行うことができます。 また、シミュレーションをし、何が起こるか観察するためシステムの機能について質問が出るかもしれません。
Simulinkを使って、ユーザーは一からのモデル化や既存モデルの変更を行うことができます。パッケージはリネアまたノンリネアの開発をサポートしています。それは個別の連続したハイブリッドな動作に基づいて作成されます。
パッケージの主要なプロパティは開発者サイトで提供されています。
- 定義済みブロックの広範な拡張可能なライブラリ
- 直感的ブロックダイアグラムの組合せと管理のための連携画像エディタ
- 設計部位の階層型セグメントモデルによる複雑なデザインを管理する能力
- すべてのシグナル、パラメータ、プロパティ、ご自身のモデルに関連づいて生成されるコードのナビゲート、作成、コンフィギュア、検索のためのModel Explorer
- 他のシミュレーションプログラムに連携、および手書きコードと組合せが可能となるアプリケーションプログラミングインターフェース (APIs)
- MATLABアルゴリズムをSimulinkと埋め込まれたシステム導入にもたらすEmbedded MATLAB™ 関数ブロック
- シミュレーションを解釈的に実行するシミュレーションモデル(ノーマル、アクセラレータ、高速アクセラレータ)、またはコンパイル時固定または可変ソルバーを用いたC-コードスピード
- シミュレーション結果検証、のちにパフォーマンスと設計における予想外の動作診断を診断するための画像デバッガとプロファイラ
- 結果分析と可視化、モデル化環境のカスタマイズ、シグナル、パラメータ、テストデータ目角化のためのMATLABへのフルアクセス
- モデル分析、モデル安定性およびモデルエラー特定のための確認ツール
ではこれからすぐにSimulink環境を概観しましょう。すでに開かれたMatlabウィンドウから次の2とおりの方法で初期化されます。
- コマンドウィンドウのSimulinkコマンドを使って
- ツールバーのSimulinkアイコンを使って
図1 Simulinkの初期化
コマンドが実行されるとライブラリ閲覧ウィンドウ(Simulink ライブラリブラウザ)が表示されます。
図2 ライブラリブラウザ
ブラウザウィンドウにはSimulinkライブラリコンポーネントの階層が含まれます。ライブラリの特定セクションを閲覧するには、マウスでそれを選べばよいだけです。すると、『Simulinkライブラリブラウザ』ウィンドウの右側にライブラリの選択可能なアイコンコンポーネントセットが表示されます。図2はSimulinkライブラリの主要セクションを示しています。
ブラウザメニューまたはツールバーボタンを使用すると、新規モデルの作成や既存モデルの更新を行うことができます。Simulinkでの作業はすべて開かれたMATLABシステムと連携して行われ、モデルプログラムによってアウトプットが提供される限りそこでは処理の実行を監視することが可能であることをお伝えします。
図3 Simulink空ウィンドウ
まず、われわれのモデルのパラメータをいくつか変更します。シミュレーションを開きます --> コンフィギュレーションパラメータ このウィンドウには多くのパラメータを伴うタブをたくさんあります。デフォルトの「ソルバー」タブに注目します。これはSimulinkモデルシステムのソルバーパラメータを設定するものです。
「シミュレーション」時にはモデル時間は開始時間によって設定されます。すなわち、開始時間(通常 0 )および終了時間 = 停止時間です。
われわれのタスクには、「開始」時間値に1 を割り当てます。「停止」時間はそのままにしておきます。
ソルバー選択肢において、「固定ステップタイプ」も変更します。ソルバー自体を離散ソルバーに、そしてステップ(固定ステップサイズ)を1に設定します。
図4 コンフィギュレーションパラメータウィンドウ
Simulink環境はサブシステムステートフローによってうまく完成します。それはイベント駆動型モデルパッケージで、有限状態自動化理論に基づいています。それによりルール連鎖に基づきシステム動作を表すことができるようになりました。それはイベントとそのイベントに応じた動作を特定するものです。
Stateflowパッケージの画像ユーザーインターフェースには以下のようなコンポーネントがあります。
- SFチャートの画像エディタ
- Stateflowエクスプローラ
- SFチャート内で必要なオブジェクトを検索するStateflowファインダ
- SFモデルのデバッガ
- リアルタイムコード生成を行う「リアルタイムワークショップ」
最も一般的に使用されるブロック図(表)。これはStateflowセクションにあります。ではそれをじっくり見ていきます。
ブロックをライブラリから移動し、その上でダブルクリックしてダイアグラムを開きます。SFチャートエディタの空ウィンドウが表示されます。これはSFチャート作成とデバッグに使用され、必要な関数を取得します。
ツールバーは左側で縦方向に表示されます。そこにはボタンが 9 個あります。
- 状態
- ヒストリジャンクション
- デフォルト遷移
- コネクティブジャンクション
- 真偽表
- 関数
- 埋め込みMATLAB関数
- ボックス
- Simulink関数呼び出し
残念なことに、本稿のコンテクストではすべてのエレメントを詳細にみていくことはできません。よって、われわれのモデルに必要なエレメント限定でかいつまんで見ていくことにします。詳細情報はMatlabヘルプ、または開発者ウェブサイトでご覧いただけます。
図5 エディタでのSFチャート閲覧
SFチャートの主要なオブジェクトは「ステート」です。それは角丸長方形で表されています。
それは排他または並列です。各ステートは親でそれには継承者があります。ステートはアクティブまたはノンアクティブでありえ、特定の手続き処理を行います。
遷移は曲線、矢印線で表され、ステートその他のオブジェクトにつなげます。遷移はソースオブジェクト上でマウスの左ボタンをクリックし、カーソルをも対象オブジェクト方向に動かすことで作成できます。遷移はそれ自体の条件を持ち、それは括弧内に記録されます。遷移手続きはブラケット内に指示されます。条件が満たされれば実行されます。対象オブジェクト確認中に実行される手続きはスラッシュによって表示されます。
代替ノード(コネクティブジャンクション)は円形で、遷移は、指定の条件により一つに定義される異なるパスを通って進むことができます。そのような場合には、特定条件に対応する遷移が選択されます。
Stateflowプロシージャ言語の記述を伴うフローグラフとして表現される関数フローグラムは、遷移および代替ノードの使用の理論ストラクチャを反映します。
「イベント」もStateflowのもうひとつの重要なオブジェクトで、非画像オブジェクトに属します。このオブジェクトはSFチャートの手順を起動します。
その手順(処理)もまた非画像オブジェクトです。それは関数を呼び、特定イベントや遷移を割り当てたりすることができます。
SFモデル内のデータは数値によって表されます。データは画像オブジェクトとしては表されません。それらはモデルのあらゆる階層で作成可能で、プロパティを有します。
2. トレーディング戦略の記述
手短に、トレーディングについてです。ここでは練習目的の Expert Advisor はたいへんシンプル、あるいは言い方を変えると原始的なものです。
自動化トレーディングシステムはシグナルを基にポジションをオープンします。基本的に周期21および55(フィボナッチの数列)を伴う指数移動の後、終値で平均化されます。EMA 21が底からのEMA 55を上にクロスする場合、ロング ポジションがオープンされます。それ以外はショート ポジションがオープンされます。
ノイズの除去には、ポジションは 21/55クロスが起こった後オープンするバー価格によってK番目のバーでオープンされます。EURUSD H1でトレードします。ポジションは1つだけオープンしています。それはテイクプロフィットまたはストップロスに到達するときにのみクローズされます。
自動化トレーディングシステムを開発、履歴をバックテストする間、トレードの全体像に特定の簡素化が認めれらることを述べたいと思います。
たとえば、システムはシグナルのブローカ実行をチェックしません。また、MQL5システムの核にトレーディングの制約を設けます。
3. Simulinkにおけるトレーディング戦略のモデル化
まずはじめに、Matlab環境に価格データ履歴をアップロードする必要があります。それをMetaTrader 5スクリプトを用いて行います。 それはデータを格納します。(testClose.mq5).
Matlabでは、これらデータ(オープン、ハイ、ロー、クローズ、スプレッド)はまたシンプルなスクリプト (priceTxt.m)を用いてロードされます。
movavg(標準Matlab関数)を使い、指数移動平均配列を作成します。
[ema21, ema55] = movavg(close, 21, 55, 'e');
バーインデックスの予備配列も作成します。
num=1:length(close);
では、次の変数を作成しましょう。
K=3; sl=0.0065; tp=0.0295;
モデル化手順を始めます。
Simulinkの空ウィンドウを作成し、それを保存するとき mts と名づけます。以下の処理はすべてビデオ形式でコピーされました。明確でない点があったり、まったく解らない場合はビデオで処理を見ることができます。
モデルを保存する際、システムは以下のエラーを印刷します。
??? ファイル"C:\\Simulink\\mts.mdl"は現在の文字エンコード、windows-1251と互換性のない文字を含んでいます。このエラーを避けるため、以下のうちの一つを行います。
1) 現在の文字エンコードからShift_JIS、windows-1252、 ISO-8859-1のうちの一つに変更するためslCharacterEncoding関数を使用する。
2) サポートされていない文字を削除する。最初のサポートされていない文字は23行目にあり、バイトオフセットは15です。
これを消去するには、モデルウィンドウをすべて閉じるだけです。そして次のコマンドを使ってエンコードを変更します。
bdclose all
set_param(0, 'CharacterEncoding', 'windows-1252');
われわれのモデルの情報ソースを指定します。
そのようは情報ソースの役割は、MetaTrader 5からの履歴データです。それは始値、高値、終値を含みます。また、比較的最近流動的になったとしても「スプレッド」も考慮します。最後に、バー開始時刻を記録します。モデル化目的のため、初期データの配列の中にはシグナルと解釈されるものもあります。それは時間の離散点における時間関数の値ベクトルとしてのものです。
それでは、"FromWorkspace"サブシステムを作成し、Matlabワークスペースからデータを復元します。Simulinkライブラリブラウザで「ポートとサブシステム」を選択します。マウスを使って、「サブシステム」ブロックをSimulinkモデルウィンドウまでドラッグします。「サブシステム」をクリックし、それに"FromWorkspace"と名前をつけ替えます。それから、ブロック上でマウスの左ボタンをダブルクリックして、それにログインし、システムへのインプットおよびアウトプット変数と定数を作成します。
「ライブラリ ブラウザ」にシグナルソースを作成するために、「シグナル処理ブロックセット」とソース(シグナル処理ソース)を選択します。マウスを使って「ワークスペースからのシグナル」ブロックをFromWorkspaceモデルのサブシステム」ウィンドウの中までドラッグします。モデルには4つのインプット シグナルがあるので、ブロックをただコピーし、さらに3つのコピーを作成するだけです。そしてすぐにこの半数がブロックで処理するか指定します。このために、ブロックを二度クリックし、プロパティに変数名を入力します。これら変数は、open、ema21、ema55、numです。ブロックに次のような名前をつけます。openシグナル、ema21 シグナル、ema55シグナル、 numシグナル。
では、『共通使用ブロック』Simulinkセクションから、チャンネルを作成(バス作成)するためのブロックを追加します。ブロックを開き、入力ナンバーを4に変更します。openシグナル、ema21シグナル、ema55シグナル、 numシグナルを「バス作成ブロック」に関連づけます。
また、入力定数をもう5個入手します。「共通使用ブロック」セクションから「定数」ブロックを追加します。値(定数値)として、変数名をspread、high、low、tp、sl、と指定します。それは次のものです。
- spread - 離散値配列
- high - 最高値の配列
- low - 最低値の配列
- tp - 絶対タームのテイクプロフィット値
- sl - 絶対タームのストップロス値
ブロックを以下のように呼びます。spread 配列、high 配列、low 配列、テイクプロフィット、ストップロス。
「ポートとサブシステム」Simulinkセクションで出力ポートブロック(Out1) を選択し、それをサブシステムウィンドウに移動します。出力ポートを5つコピーします。最初のひとつは、「バス作成ブロック」に接続し、その他は選択的にspread配列、high配列、low 配列、テイクプロフィット、ストップロスに関連づけます。
最初のポートに名前を付けなおしてpriceとし、その他は出力変数名を名づけます。
トレーディングシグナル作成のために、Simulinkセクション「数学的処理」より追加のブロック(Add)を挿入します。それを emas 微分と呼びます。ブロック内で、シグナルリストをc + + から + - に変更します。Ctrl+ K キーの組合せでブロックを 90 ° 時計回りに回転します。ema21シグナルブロックを "+" 入力に、ema55シグナルブロックを "-"に関連づけます。
それから、「シグナル処理」の「シグナル処理ブロックセット」セクションから「遅延」ブロックを挿入します。それを K ディレイと名づけます。このブロックの「ディレイ」(サンプル)フィールドに、K 変数名を入力します。それを以前のブロックに関連づけます。
emas 微分とK ディレイは 、変更があるモデル化段階でのみ計算コントロールシグナルのフロント(レベル差)をフォーマットします。すこし後で作成するサブシステムはすくなくともエレメントが 1つそのシグナルレベルを変更するとアクティブになります。
そして、 Simulinkの「共通使用ブロック」セクションから、マルチプレクサーwithと (Mux) ブロックを追加します。同様に、ブロックを 90 ° 時計回りに回転します。遅延ブロックのシグナルラインを2つに分割し、それをマルチプレクサーに関連づけます。
StateflowセクションよりChartブロックを挿入します。チャート入力2件の到着イベント(買いおよび売り)と2件の発信イベント(OpenBuy および OpenSell)を追加します。「買い」イベントのトリガー値は「下降」(ネガティブフロントによるサブシステムの起動)に設定し、「売り」イベントには「上昇」(ネポジティブフロントによるサブシステムの起動)に設置します。OpenBuyおよびOpenSellイベントへのトリガー値(「トリガー」)は関数呼び出し(「コーリング」)ポジションに設定します。(サブシステムの起動は与えられるS関数の動作ロジックによって決定されます。)
遷移は3つの選択可能なノードのデフォルトによって作成します。最初のノードは遷移によって二番目のノードに関連付けます。条件と「買い」手続き設定{OpenBuy;}、そして三番目に「売り」手続き設{OpenSell;}です。チャート入力をマルチプレクスと2つのアウトプットに関連づけます。別のマルチプレクスで、それは一番目からコピーできます。最終ブロックは出力ポートに関連づけます。それはアナログのポートからコピーし、「買い」/「売り」を呼びます。
それから、忘れかけていたことがありました!適切に動作するモデル化のためには、バーチャルチャンネルオブジェクトを作成する必要があります。それを Matlab ワークスペースに配置します。そのために、「ツール」メニューから「バスエディタ」に入ります。エディタ内では、アイテム「バス追加」を選択します。それをInputBusと呼びます。
入力変数名に応じてopen、ema21、ema55、numなどのエレメントを挿入します。「バスクリエータ」を開き、バスオブジェクトを介してプロパティ指定の隣のチェックボックスをクリックします。言い換えると、ブロックを作成したバーチャルチャンネルオブジェクトに関連づけます。バーチャルチャンネルとは、シグナルが画像的にのみ結びつけられることを意味します。それはメモリ分布に影響はありません。
変更内容をサブシステムウィンドウに保存します。これでFromWorkspaceサブシステムの作業は終わりです。
ここから「ブラックボックス」作成です。それは着信シグナルに基づくブロックで、情報処理を行い、トレーディングの判断をします。もちろん、それはコンピュータプログラムというより、われわれが作成する必要があります。結局のところ、ただわれわれだけがシステムがトレードを行う条件を決定できるのです。また、ブロックはシグナル形式で完了した取引情報を表示する必要があります。
必要なブロックは「チャート」と呼ばれStateflowセクションに配置されます。それはすでに知っていますよね?「ドラッグ&ドロップ」を使用し、それをモデルウィンドウに移動します。
図6 入力サブシステムのブロックとStateFlowチャート
チャートを開き、その中にデータを入力します。まず、チャンネルオブジェクトを作成しますFromWorkspaceサブシステムのときと同じ要領です。しかしそのときと違っているのは、以前の場合はワークスペースからシグナルが送られてきましたが、今回は取得した結果から返されます。よってそのオブジェクトをOutputBusと呼びます。そのエレメントbarOpen、OpenPrice、TakeProfit、StopLoss、 ClosePrice、barClose、Comment、PositionDir、posN、 AccountBalanceとなります。
では、構成を始めます。チャートウィンドウで、デフォルトの遷移を表示します。 (# 1).
条件と手順について次を指示します。
[Input.num>=56 && Input.num>Output.barClose] {Output.barOpen=Input.num;i = Input.num-1;Output.posN++;}
この条件は、入力バー数が前回ポジションのクローズ時より多いときと同様、入力バー数が最低でも56であればデータが処理されることを意味します。オープンバーは、インデックス変数 i :インデックス(0からスタート)、着信バーに割り当てられます。そしてオープンポジション数は1ずつ増加します。
2番目の遷移にはオープンポジションが最初のものでない場合に実行されます。それ以外は、三番目の遷移が実行されます。これはアカウントのバランス変数(Output.AccountBalance)を割り当てます。
4番目の遷移はチャートがOpenBuyイベントによって初期化されたら実行されます。そのような場合は、ポジションは購買に向かい(Output.PositionDir = 1)、始値はオープン時のバー価格に等しくなります。スプレッドを考慮します(Output.OpenPrice = Input.open + spread [i] * 1e-5)。出力シグナル、StopLossおよびTakeProfitの値もまた指定されます。
OpenSellイベントが起こると、5番目の遷移に続いてフローが きて、その値を出力シグナルに設定します。
6番目の遷移はポジションがロングの場合に実現されます。それ以外はフローは7番目の遷移に続きます。
8番目の遷移はバー最高値がテイクプロフィットレベルに到達したかどうか、またはバー最小値がストップロスレベルに到達したか確認します。それ以外では、インデックス変数の値 i は1ずつ増加します(9番目の遷移)。
10番目の遷移はストップロス時に起こる条件を確定verifiesします。バー最小値はストップレベルをクロスしています。フローが11番目の遷移に続き、そして12番目ではポジションオープンとクローズ時の価格差の値、現在のアカウントバランス、バークローズのインデックスが確定されます。
10番目の遷移が確認されなければ、ポジションはテイクプロフィットでクローズされます(13番目の遷移)。そして14番目からフローは12番目の遷移に続きます。
ショートポジションへの遷移の手順と条件は逆です。
ついにチャートに新規変数を作成しました。自動的にそれらをわれわれのモデルに統合するため、モデルを直接チャートウィンドウで実行する必要があります。「シミュレーション開始」をクリックして行います。それは音楽プレーヤーの「再生」ボタンに似ています。この時点でStateflowシンボルウィザード(SF マスターオブジェクト) が起動し、作成したオブジェクトを保存するよう薦めます。SelectAllボタンを押し、それから「作成」ボタンをクリックします。オブジェクトは作成されました。「モデルブラウザ」を開きます。左で「モデル階層」の「チャート」をクリックします。データタイプ(「データタイプ」)でオブジェクトをソートします。
「追加」および「データ」メニューコマンドを使ってデータをもっと追加します。最初の変数Inputを呼びます。「スコープ」の値を「インプット」に変え、「バス」にタイプします。<バスオブジェクト名> . それから、名前、前に作成したチャンネルInputBusをフィールドに直接を入力します。これでわれわれの「入力変数」はInputBusタイプになります。「ポート」の値を1に設定します。
Output変数についても同じ処理を完了します。ただそれはOutput ScopeタイプおよびOutput Busタイプを持つ必要があります。
スコープを変数、high、low、sl、 tp、spread のスコープを「インプット」の値に変更します。それぞれに次の順番でポート番号を設定します。: 3、4、6、5、2。
また、変数LotsのスコープをConstantに変更します。「値属性」タブで1、OpenBuyイベント、OpenSellイベントを入力します。「イニシャル」(右側)フィールドの「インプット」について。 イベントでは、「関数呼び出し」についてのトリガー値を変更します。
定数スコープを伴い、初期変数lenを作成します。「値属性」タブの「初期値」フィールドでm 関数長(クローズ)を入力します。これでクローズ配列の長さと同じになります。それはMatlabワークスペースに配置されています。
ハイおよびロー変数には、「サイズ」フィールドに値[len 1] を入力します。それから、メモリには、ハイとローの配列サイズを逆にして値[len 1]とします。
また、「値属性」タブの変数 K を指示します。ワークスペースから取った「初期値」フィールド(右側)の実際値 K。
結果、7つの入力ポートと1つの出力ポートを備えたチャートのサブシステムを得ました。そのような方法でブロックを配置し、入力イベント () ポートが一番下に来るようにします。「ポジション処理」ブロックの名前をつけ替えます。チャート自体では、またブロック名を表示します。FromWorkspaceサブシステムのブロックと 「ポジション処理」を適切なポートを通じて結合します。そしてブロックの色を変えます。
「ポジション処理」サブシステムは、入信のOpenBuyイベントまたはOpenSellイベントによって「目覚めさせられた」場合のみ、機能します。この方法で、不要な計算を避けるためサブシステムの処理を最適化します。
図7 FromWorkspaceおよびポジション処理サブシステム
ここで、Matlabワークスペースに処理結果を印刷するためのサブシステムを作成し、それを「ポジション処理」サブシステムとコンバインする必要があります。もっとも簡単なタスクです。
"ToWorkspace"サブシステムをを作成し、結果をワークスペースに取得します。"FromWorkspace"サブシステムを作成したときの手順を繰り返します。ライブラリブラウザでSimulink Ports & Subsystemsセクションを選択します。マウスを使って「サブシステム」ブロックをSimulinkモデルウィンドウまでドラッグします。「サブシステム」をクリックし、それに"ToWorkspace"と名前をつけ替えます。ブロックを「ポジション処理」サブシステムとコンバインします。
左のマウスボタンでブロックをダブルクリックしてそこに変数ログを作成します
サブシステムはノンバーチャルバスであるOutputBusオブジェクトからデータを受け取るので、このチャンネルからシグナルを選択する必要があります。そのため、 ライブラリブラウザでSimulinkの「共通使用ブロック」セクションを選択し、「バスセレクタ」を追加します。ブロックはそのようなシグナルが10個必要なところ、1つのインプットシグナルと2つのアウトプットシグナルを得ます。
ではブロックをインプットポートに関連づけます。「シミュレーション開始」ボタンを押します。(これがわれわれの「再生」ボタンです。)コンパイラがモデルの構築を始めます。ビルドはうまくいきませんが、バス選択ブロックに入力シグナルを作成します。ブロックを入力したら、左側のウィンドウに必要なシグナルが表示されるのがわかります。それはOutputBusを介して送信されるものです。「選択」ボタンを使ってそれらはすべて選択され、右側「選択されたシグナル」に移動する必要があります。
図8 バスセレク タブロック パラメータ
再びSimulinkライブラリブラウザの「共通使用ブロック」セクションを参照し、Mux multiplexブロックを追加します。それは、入力数を指示します。入力数は10です。
Simulinkライブラリブラウザの"Sinks"セクションにログインし、 ToWorkspaceブロックをサブシステムウィンドウに移動します。そこで変数"AccountBalance"の新しい名前を指示し、出力フォーマット(保存フォーマット)を「ストラクチャ」から「配列」に変更します。ブロックをマルチプレクスとコンバインします。そして出力ポートを削除します。もう必要がないためです。ブロックの色をカスタマイズします。ウィンドウを保存します。これでサブシステムは準備できました。
モデル構築の前に、ワークスペースに変数があるか確認する必要があります。次の変数があるはずです。: InputBus, K, OutputBus, close, ema21, ema55, high, low, num, open, sl, spread, tp
num (終了)を定義するパラメータとして「ストップタイム」値を設定します。処理済みベクトルは長さを持つことを意味します。それは num 配列の最終エレメントによって設定されたものです。
モデル構築に先立ち、以下のコマンドを使ってコンパイラを選択する必要があります。
mex-setup
外部インターフェー(MEX)ファイル構築のコンパイラを選択します。
mexにインストールしたコンパイラの配置をさせたいですか [y] / n?y を選択します。
コンパイラを選択します。
[1] Lcc-win32 C 2.4.1 in C:\PROGRA~2\MATLAB\R2010a\sys\lcc
[2] Microsoft Visual C++ 2008 SP1 in C:\Program Files (x86)\Microsoft Visual Studio 9.0
[0] None
コンパイラ:2
ご覧のとおり、私はMicrosoft Visual C ++ 2008 compiler SP1を選択しました。
構築を始めていきます。「シミュレーション開始」ボタンを押します。エラーです。:Stateflowインターフェースエラー:ポート幅ミスマッチです。 "spread"(#139) のインプットはスカラーを期待します。シグナルは59739エレメントを伴なう一次元ベクトルです。
変数"spread"はダブルタイプを持ちませんが、Simulinkからのシグナルからそのタイプを受け継ぎます。
「モデルブラウザ」では、この変数のために「継承Simulinkと同じ」を、「サイズ」フィールドには"-1"を指定します。変更を保存します。
モデルをもう一度実行します。コンパイラは動作します。いくつか重要ではない警告が表示されます。そして、40秒以内に モデルは60,000バーに近いデータを処理します。トレードは2001年01月01日 00:00 から2010年08月16日11:00まで処理されます。オープンポジションの合計数は461です。次のクリップで、モデルの動作方法を見ます。
4. MQL5への「戦略」導入
これで、われわれの自動化トレーディングシステムはSimulinkにコンパイルされました。ここでは、このトレーディングの考え方をMQL5環境に変換する必要があります。Simulinkブロックとオブジェクトに取り組む必要がありましたが、それによってわれわれのトレーディング Expert Advisor のロジックを表現しました。現在のタスクはロジックのトレーディングシステムをMQL5 Expert Advisorに変換することです。
ただし、必ずしもMQL5コードで定義される必要のないコードもあることを知っておく必要があります。というのも、そういった関数は非表示にできるからです。 実際のコードでどの行がどのブロックにひもづくかできるだけ多くについて詳細を述べていくようにしたいと思います。ときには間接の関連もあるかもしれません。ブロックやオブジェクトのインターフェースインターフェース接続を反映することもあるかもしれません。
この項を始める前に、『初心者のためのMQL5にExpert Advisors を書くための段階的ガイド』稿に注意を向けていただきたいと思います。この稿はMQL5にExpert Advisors を書くための主要な考え方や基本ルールをやさしく理解しやくいように書かれています。今はそれに時間をさくのはやめておきます。ここからMQL5 コードの行をいくつか使っていきます。
4.1 "FromWorkspace"サブシステム
たとえば、"FromWorkspace"サブシステムに「オープンシグナル」ブロックがあります。Simulinkには、バックテストの間にオープンバー価格を取得し、トレーディングシグナルが受け取られた場合にこの価格でポジションをオープンするためにそれが必要です。このブロックは明らかにMQL5コードにはありません。なぜなら Expert Advisorはトレーディングシグナルを受け取ったら即座に価格情報を要求するからです。
Expert Advisorでは、移動平均から受け取られたデータを処理する必要があります。そのあtめ、それらのために動的配列と対応する予備変数をハンドルとして作成します。
int ma1Handle; // Moving Average 1 indicator handle: block "ema21 signal" int ma2Handle; // indicator handle Moving Average 2: block "ema55 signal" ma1Handle=iMA(_Symbol,_Period,MA1_Period,0,MODE_EMA,PRICE_CLOSE); // get handle of Moving Average 1 indicator ma2Handle=iMA(_Symbol,_Period,MA2_Period,0,MODE_EMA,PRICE_CLOSE); // get handle of Moving Average 2 indicator double ma1Val[]; // dynamic array for storing the values of Moving Average 1 for every bar: block "ema21 signal" double ma2Val[]; // dynamic array for storing the values of Moving Average 2 for every bar: block "ema55 signal" ArraySetAsSeries(ma1Val,true);// array of indicator values MA 1: block "ema21 signal" ArraySetAsSeries(ma2Val,true);// array of indicator values MA 2: block "ema55 signal"
All other lines, which somewhat affect the moving ema21 and ema55, can be considered as auxiliary.
"Take Profit" and "Stop Loss" are defined as input variables:
input int TakeProfit=135; // Take Profit: Take Profit in the FromWorkspace subsystem input int StopLoss=60; // Stop Loss: Stop Loss in the FromWorkspace subsystemEURUSDには5個の有効t桁があることを考慮しつつ、テイクプロフィットとストップロスの値は以下の方法で更新される必要があります。
int sl,tp; sl = StopLoss; tp = TakeProfit; if(_Digits==5) { sl = sl*10; tp = tp*10; }
"spread"、"high"、 "low"配列は値を提供するために使われます。それらは、トレーディング条件を特定するため、適切な価格データの行列の形式で履歴データ提供をする役割があります。
それらは明確にコードで表されていません。ただ、たとえば"spread"配列はask価格のストリームを形成する必要があります。他の2つはポジションをクローズする条件を決定するのに必要です。それはコードでは指定されません。なぜかというと、特定の価格レベルに到達するとそれらは自動的にMetaTrader 5で実行されるからです。
"numシグナル"ブロックは予備でExpert Advisorのコードでは表示されません。
"emas differential"ブロックは、差異を見つけることでショートまたはロングポジションをオープンする条件を確認します。"K ディレイ" は値 Kに平均である配列についてラグを作成します。
「買い」または「売り」イベントが作成されました。それはポジションオープンサブシステムのための入力イベントです。
コードでは、以下のように表現されます。
// event Buy (activation by the negative front) bool Buy=((ma2Val[1+K]-ma1Val[1+K])>=0 && (ma2Val[K]-ma1Val[K])<0) || ((ma2Val[1+K]-ma1Val[1+K])>0 && (ma2Val[K]-ma1Val[K])==0); // event Sell (activation by the positive front) bool Sell=((ma2Val[1+K]-ma1Val[1+K])<=0 && (ma2Val[K]-ma1Val[K])>0)|| ((ma2Val[1+K]-ma1Val[1+K])<0 && (ma2Val[K]-ma1Val[K])==0);「ポジション」オープンサブシステム"OpenBuy"イベントおよび"OpenSell"イベントそのものを作成します。それは「ポジション処理」サブシステムで条件と手順を使って処理されます。
4.2 「ポジション処理」サブシステム
サブシステムはOpenBuy OpenSellイベントを処理することで動作し始めます。
サブシステムの最初の遷移には、条件の一つにバー数が56以下でない、というのがあります。それはコード内でそのような条件チェックを介して指示されます。
if(Bars(_Symbol,_Period)<56) // 1st transition of the «Position handling»subsystem : condition [Input.num>=56] { Alert("Not enough bars!"); return(-1); }
遷移の二番目の条件は、オープンバーのナンバーがクローズバーのナンバー(Input.num; Output.barClose)よりも高い必要があるというものです。すなわちポジションはクローズになっている、ということです。
コードでは次のように指示されます。
//--- 1st transition of the «Position handling» subsystem: condition [Input.num>Output.barClose] bool IsBought = false; // bought bool IsSold = false; // sold if(PositionSelect(_Symbol)==true) // there is an opened position { if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) { IsBought=true; // long } else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL) { IsSold=true; // short } } // check for opened position if(IsTraded(IsBought,IsSold)) { return; } //+------------------------------------------------------------------+ //| Function of the check for opened position | //+------------------------------------------------------------------+ bool IsTraded(bool IsBought,bool IsSold) { if(IsSold || IsBought) { Alert("Transaction is complete"); return(true); } else return(false); }
4番目の遷移はロングポジションのオープンに関連しています。
それは以下のように表されます。
// 4th transition procedures of the «Position handling» subsystem: open long position mrequest.action = TRADE_ACTION_DEAL; // market buy mrequest.price = NormalizeDouble(latest_price.ask,_Digits); // latest ask price mrequest.sl = NormalizeDouble(latest_price.bid - STP*_Point,_Digits); // place Stop Loss mrequest.tp = NormalizeDouble(latest_price.bid + TKP*_Point,_Digits); // place Take Profit mrequest.symbol = _Symbol; // symbol mrequest.volume = Lot; // total lots mrequest.magic = EA_Magic; // Magic Number mrequest.type = ORDER_TYPE_BUY; // order to buy mrequest.type_filling = ORDER_FILLING_FOK; // the specified volume and for a price, // equal or better, than specified mrequest.deviation=100; // slippage OrderSend(mrequest,mresult); if(mresult.retcode==10009 || mresult.retcode==10008) // request completed or order placed { Alert("A buy order has been placed, ticket #:",mresult.order); } else { Alert("A buy order has not been placed; error:",GetLastError()); return; }
4番目の遷移はショートポジションのオープンに関連しています。
それは以下のように表されます。
// 5th transition procedures of the «Position handling» subsystem: open a short position mrequest.action = TRADE_ACTION_DEAL; // market sell mrequest.price = NormalizeDouble(latest_price.bid,_Digits); // latest bid price mrequest.sl = NormalizeDouble(latest_price.ask + STP*_Point,_Digits); // place a Stop Loss mrequest.tp = NormalizeDouble(latest_price.ask - TKP*_Point,_Digits); // place a Take Profit mrequest.symbol = _Symbol; // symbol mrequest.volume = Lot; // lots mrequest.magic = EA_Magic; // Magic Number mrequest.type= ORDER_TYPE_SELL; // sell order mrequest.type_filling = ORDER_FILLING_FOK; // in the specified volume and for a price, // equal or better, than specified in the order mrequest.deviation=100; // slippage OrderSend(mrequest,mresult); if(mresult.retcode==10009 || mresult.retcode==10008) // request is complete or the order is placed { Alert("A sell order placed, ticket #:",mresult.order); } else { Alert("A sell order is not placed; error:",GetLastError()); return; }
サブカテゴリ内のその他の遷移は、明らかにExpert Advisorには存在しません。MQL5では適切な手順(停止の起動またはテイクプロフィットレベルの達成)が自動で実行されるからです。
「ワークスペース」サブシステムはMQL5コードでは表されません。なぜならそのタスクは Matlabワークスペースで出力を行うからです。
おわりに
例としてシンプルなトレーディングの考え方を取り入れ、Simulinkに自動化トレーディングシステムを作成し、そこで履歴データのバックテストを実行しました。最初は質問に煩わされました。「MQL5コードで速くトレーディングシステムを導入することができるのに、この面倒をぜんぶやる意味はあるのだろうか?」
もちろん、システム作成手順の可視化もその動作のロジックもなく行うこともできます。しかし、最往々にしてこれは経験あるプログラマや単に才能ある人々しかできることではありません。 most often than not新しい条件と関数を備えたトレーディングシステムがいきわたってくると、ブロックダイアグラムを作成し動作させることは明らかにトレーダーのタスクです。
また、私はMQL5言語に対してSimulink言語の有能性に異議を唱えるものではないことも申し上げたいと思います。ただブロックデザインを使用して自動トレーディングシステムを作る方法をお見せしたまでです。たぶん将来、MQL5開発者は戦略のビジュアルコンストラクタを作成されることでしょう。そしてそれはExpert Advisorsを各プロセスを促進することと思います。
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/155
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索