プログラムを学ぶ第一歩は、既存のプログラムを動かしたり、改造したりすることです。
サンプルプログラムを見てみよう
まずはスクリプトの構成を見てみましょう。はじめての方は暗号に見えるかもしれません。
ファイル構成
- 1~5行目 ヘッダーコメント ファイルの作者等のコメント
- 6~9行目 ファイル情報 バージョンや著作権などの設定
- 10~18行目 input変数の宣言 EAのパラメーター設定で入力できる変数を宣言する
- 20行目 ロットの補正(設定値が1.0枚=10,000通貨単位なので、補正しています。証券会社によって違うので適宜変えてください。楽天MT4は1.0枚=100,000通貨単位です)
- 21~246行目 状態クラスの定義
- 247~262行目 起動時の処理(EAの起動時に実行)
- 263~271行目 終了時の処理
- 272~298行目 ここがメイン。新しい値動きが追加されるたびに実行される処理。状態変化がないかチェックして、買いシグナル、売りシグナルが発生したら処理を行い次の状態に移行する。
- 304~最終行 売りシグナル、買いシグナル判定関数。ここを自由に変更してください。
//+------------------------------------------------------------------+ //| template.mq4 | //| castanet | //| https://fx.castanet.tokyo | //+------------------------------------------------------------------+ #property copyright "castanet" #property link "https://fx.castanet.tokyo" #property version "1.00" #property strict //--- input parameters input double sell_threshold=75; input double buy_threshold=25; input double set_lots=2; input int stop_pips=1000; input int limit_pips=200; input int stop_enable=0; input int limit_enable=0; input int magic_number = 10415518; double lots = set_lots / 10.0; // 状態基底クラス class CStatus { private: int m_status; protected: static int g_ticket; static int ticket() { return g_ticket; } void ticket(int tk) { g_ticket = tk; } public: CStatus(int st) { m_status = st; } virtual int sell_signal() { return status(); } virtual int buy_signal() { return status(); } virtual int check() { return status(); } int status() { return m_status; } }; int CStatus::g_ticket = -1; class init_pos : public CStatus { public: init_pos() : CStatus(1) {} virtual int sell_signal() { double stop_level = 0; if (stop_enable) { stop_level = NormalizeDouble(Bid + stop_pips * Point, Digits); } double limit_level = 0; if (limit_enable) { limit_level = NormalizeDouble(Bid - limit_pips * Point, Digits); } Print("Bid=", Bid, "Stop=", stop_level, "Limit=", limit_level); int result = OrderSend( Symbol(), OP_SELL, lots, Bid, 30, stop_level, limit_level, NULL, magic_number, 0, Red ); int ErrCode = GetLastError(); if (ErrCode == 0) { ticket(result); return 5; } else { Print( "ErrCode=" + (string)ErrCode ); return status(); } } virtual int buy_signal() { double stop_level = 0; if (stop_enable) { stop_level = NormalizeDouble(Ask - stop_pips * Point, Digits); } double limit_level = 0; if (limit_enable) { limit_level = NormalizeDouble(Ask + limit_pips * Point, Digits); } Print("Ask=", Ask, "Stop=", stop_level); int result = OrderSend( Symbol(), OP_BUY, lots, Ask, 30, stop_level, limit_level, NULL, magic_number, 0, Blue ); int ErrCode = GetLastError(); if (ErrCode == 0) { ticket(result); return 4; } else { Print( "ErrCode=" + (string)ErrCode ); return status(); } } virtual int check() { // オーダー情報取得 for ( int i = 0; i < OrdersTotal(); i++ ){ // オーダー選択 if ( OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) ) { // オーダー確認 if ( OrderMagicNumber() != magic_number || OrderSymbol() != Symbol() ) { continue; } // オーダーあり ticket(OrderTicket()); if ( OrderType() == OP_BUY ) { return 2; } else if ( OrderType() == OP_SELL ) { return 3; } else { // とりあえず、決済中にしておく return 6; } } } return status(); } }; class buy_pos : public CStatus { public: buy_pos() : CStatus(2) {} virtual int sell_signal() { // パラメータが変わってる時を考慮して、ロット数を取得 double _lots = lots; if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) { _lots = OrderLots(); } int result = OrderClose( ticket(), _lots, Bid, 30, Goldenrod ); int ErrCode = GetLastError(); if (result) { return 6; } else { return status(); } } virtual int check() { // オーダー選択 if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) { if (OrderCloseTime() != 0) { // キャンセルされた ticket(-1); return 1; } } else { ticket(-1); return 1; } return status(); } }; class sell_pos : public CStatus { public: sell_pos() : CStatus(3) {} virtual int buy_signal() { // パラメータが変わってる時を考慮して、ロット数を取得 double _lots = lots; if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) { _lots = OrderLots(); } int result = OrderClose( ticket(), _lots, Ask, 30, Goldenrod ); int ErrCode = GetLastError(); if (result) { return 6; } else { return status(); } } virtual int check() { // オーダー選択 if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) { if (OrderCloseTime() != 0) { // キャンセルされた ticket(-1); return 1; } } else { ticket(-1); return 1; } return status(); } }; class buy_order : public CStatus { public: buy_order() : CStatus(4) {} virtual int check() { // オーダー選択 if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) { if (OrderCloseTime() != 0) { // キャンセルされた ticket(-1); return 1; } if (OrderType() == OP_BUY) { return 2; } } else { ticket(-1); return 1; } return status(); } }; class sell_order : public CStatus { public: sell_order() : CStatus(5) {} virtual int check() { // オーダー選択 if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) { if (OrderCloseTime() != 0) { // キャンセルされた ticket(-1); return 1; } if (OrderType() == OP_SELL) { return 3; } } else { ticket(-1); return 1; } return status(); } }; class close_order : public CStatus { public: close_order() : CStatus(6) {} virtual int check() { // オーダー選択 if ( OrderSelect( ticket(), SELECT_BY_TICKET ) ) { if (OrderCloseTime() != 0) { ticket(-1); return 1; } } else { ticket(-1); return 1; } return status(); } }; CStatus *current; CStatus *StatusArray[7]; int status = 1; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- StatusArray[1] = new init_pos(); StatusArray[2] = new buy_pos(); StatusArray[3] = new sell_pos(); StatusArray[4] = new buy_order(); StatusArray[5] = new sell_order(); StatusArray[6] = new close_order(); status = 1; current = StatusArray[1]; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- for (int i = 1; i < 7; i++) { delete StatusArray[i]; } } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- int next = status; next = current.check(); if (next != status) { Print("ポジションチェックで状態変化:", status, "→", next); status = next; } current = StatusArray[status]; // 売りシグナルチェック if ( is_sell_signal() ) { next = current.sell_signal(); } // 買いシグナルチェック if ( is_buy_signal() ) { next = current.buy_signal(); } if (next != status) { Print("シグナルで状態変化:", status, "→", next); status = next; } current = StatusArray[status]; } //+------------------------------------------------------------------+ // 売シグナル判定関数です。if文の関数を他のテクニカルインジケータ―関数に変えてみてください bool is_sell_signal() { bool ret = false; if ((iRSI(NULL, 0, 14, PRICE_CLOSE, 0)) > sell_threshold) { ret = true; } return ret; } // 買シグナル判定関数です。if文の関数を他のテクニカルインジケータ―関数に変えてみてください bool is_buy_signal() { bool ret = false; if ((iRSI(NULL, 0, 14, PRICE_CLOSE, 0)) < buy_threshold) { ret = true; } return ret; }