KOSEN{BLOG}について

Moving Average.mq4について

とりあえずプログラムを見てみる

個人的な見解にはなるんですが、

プログラミングは教材とかで関数など一つ一つ見て覚えていくより

サンプルコードを見ながら

  • どのように書かれてるのか
  • どこに書かれているのか
  • どんな使い方をしているのか

などを把握していきながらの勉強のほうが身につきやすいと考えてます。

なので今回はサンプルコードを見ながら一つ一つ分解して解説していこうと思います。

以下に移動平均線のEAのサンプルコードを貼っておきます。

長いのでクリックしたら見えるようにしています。

一回一回ここに戻ってこなくてもいいように解説する際は該当するコードとともに行います。

homeで目次まで戻ることができます。)

MEMO

今回使用するサンプルコードはメタエディタにデフォルトで入っていたものを使用しています。

Moving Average.mq4
//+------------------------------------------------------------------+
//|                                               Moving Average.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "Moving Average sample expert advisor"

#define MAGICMA  20131111
//--- Inputs
input double Lots          =0.1;
input double MaximumRisk   =0.02;
input double DecreaseFactor=3;
input int    MovingPeriod  =12;
input int    MovingShift   =6;
//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)
  {
   int buys=0,sells=0;
//---
   for(int i=0;i0) return(buys);
   else       return(-sells);
  }
//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double lot=Lots;
   int    orders=HistoryTotal();     // history orders total
   int    losses=0;                  // number of losses orders without a break
//--- select lot size
   lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);
//--- calcuulate number of losses orders without a break
   if(DecreaseFactor>0)
     {
      for(int i=orders-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false)
           {
            Print("Error in history!");
            break;
           }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL)
            continue;
         //---
         if(OrderProfit()>0) break;
         if(OrderProfit()<0) losses++;
        }
      if(losses>1)
         lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//--- return lot size
   if(lot<0.1) lot=0.1;
   return(lot);
  }
//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void CheckForOpen()
  {
   double ma;
   int    res;
//--- go trading only for first tiks of new bar
   if(Volume[0]>1) return;
//--- get Moving Average 
   ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//--- sell conditions
   if(Open[1]>ma && Close[1]ma)
     {
      res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);
      return;
     }
//---
  }
//+------------------------------------------------------------------+
//| Check for close order conditions                                 |
//+------------------------------------------------------------------+
void CheckForClose()
  {
   double ma;
//--- go trading only for first tiks of new bar
   if(Volume[0]>1) return;
//--- get Moving Average 
   ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//---
   for(int i=0;ima && Close[1]ma)
           {
            if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,White))
               Print("OrderClose error ",GetLastError());
           }
         break;
        }
     }
//---
  }
//+------------------------------------------------------------------+
//| OnTick function                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- check for history and trading
   if(Bars<100 || IsTradeAllowed()==false)
      return;
//--- calculate open orders by current symbol
   if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
   else                                    CheckForClose();
//---
  }
//+------------------------------------------------------------------+

宣言や定義など

コメントアウト //と/**/

複数行コメントは /* で始まり */ で終わります。

単一行コメントは // で始まり改行で終わります。
単一行コメントは、複数行コメント内でも使用する事が出来ます。

プログラミングでは、処理の内容などのメモ書きを結構します。

しかし、それらがプログラムの動作に影響があってはだめなので
このコメントアウト(//と/**/)を使い動作に関係ないですよーってしてあげないとだめです。

//+------------------------------------------------------------------+
//|                                               Moving Average.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              http://www.mql4.com |
//+------------------------------------------------------------------+

上記はコメントアウトされた記述です。
//はその行のそれ以降の文字をコメントアウトしてます。

MEMO
+------------------------------------------------------------------+
こいつは実際のところ無くても大丈夫ではあります。
しかし、こいつを使ったほうが見やすいです。
/*+------------------------------------------------------------------+
|                                               Moving Average.mq4 |
|                   Copyright 2005-2014, MetaQuotes Software Corp. |
|                                              http://www.mql4.com |
+------------------------------------------------------------------+*/

また、先ほどは単一行のコメントアウトを使っていたが
上記のように複数行のコメントアウトでも書くことができます。
どちらを使っても構わないと思います。

プログラムプロパティ #property

「#property」は、 プログラミングの付属情報のようなもので、EAに関する情報を表示するために使います。
プログラムの動作には関係ありません。

例えば、作成者名、作成者のサイトURL、プログラムのバージョン情報など。

今回は 作成者名、作成者のサイトURL、プログラムが何なのかが書かれています。

情報は、MT4画面左側の「ナビゲーター」からEA名をダブルクリックすればそのEAのサブウィンドウが開きますが、そのバージョン情報に表示されます。

#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "http://www.mql4.com"
#property description "Moving Average sample expert advisor"

マクロ代入 #define

「define」 ですが、これま単に定義するだけの命令文 になります。

#define MAGICMA  20131111

今回はMAGICMAを後ろの数字 20131111に置き換えるとういことになります。

マジックナンバーは、
ポジション管理に直結する必要不可欠な要素なのでEAを作る際は必ず必要です。

同じ口座アカウントで複数のEA/ロジックを同時稼働するとき
ポジション毎にマジックナンバーを割り当てて管理することが可能になります

注意

このマジックナンバーが管理されていないと、まったく関係のないEAのポジションを勝手に決済してしまったりするのでしっかり管理しましょう。

変数 int,doubleなど

次はinputの話かと思いますが、

その前に変数についてかるーーく書いておきます。

まず、 変数とは何か?ご自分でこの問に答えてみてください。
あなたはおいくつですか?
5年後、あなたはいくつになっていますか?
年齢は、時間の経過とともに変化します。つまり、あなたの年齢が変数なのです。

すなわち、変数の特徴は何かしらの変化とともに変化することです。
例えば上記で示した例のように時間の変化により年齢が変わるみたいな感じです。

変数にはそれぞれ一定のタイプがあります。

  • 整数--int
  • 実数(小数も可)--double
  • 文字列--string
  • 真または偽--bool

基本的にこの四つは頭に入れておきましょう。
それぞれ使い方など軽く説明します。

変数を宣言する場合以下のような形で宣言します。
[ 変数タイプ] [ 識別子] = [ 変数 値];

MEMO

識別子とは定数や変数関数などの実体に対して与える名称の事です。
最初の文字に数字を使う事はできず長さの上限は63文字です。
使用出来る文字は、

・0~9の数字

・A~Z,a~zの英字

・アンダーライン( _ )

となってます。

int age = 20;
double height = 1.66;
string name = "い。";
bool trend = false;

上記に例を示しました。

「int」は整数のみ、「double」は少数も大丈夫

「string」は文字列なので日本語も使えます。必ず「 ”(ダブルクォーテーション)」で挟んでください

「bool」は「true」「false」の二つしか受け取れません。

注意

MQL4 言語は大文字小文字を区別します。

複数の変数を同じ名前で大文字小文字を変えて宣言する場合、異なる変数となります。

「Age」「age」は別物です。

外部パラメーター input

テクニカルインジケーターのパラメーターや、取引ロット数、マジックナンバーなどは、
EAの使用者が自由に設定や変更したい数値です。

このような場合、「input」の後にこれらの数値を変数として宣言すれば、外部パラメーターとして利用できます。

外部パラメーターの数値は、
そのEAのサブウィンドウからユーザーが自由に設定や変更ができます。

input double Lots          =0.1;
input double MaximumRisk   =0.02;
input double DecreaseFactor=3;
input int    MovingPeriod  =12;
input int    MovingShift   =6;

今回のコードを上記に示しました。
五つのパラメーターをユーザーが変更可能ということになります。
例えば一番上の「Lots」ですが、0.1とあるがユーザーが変更すれば1にも0.01にも変えれます。

簡単に言うと、先ほど説明した変数はその時に決まりユーザーは変更できませんが
「input」を使うとユーザーがこのEAを使う前に変更したりできるようになる。ってことです。

MEMO

コードに書かれている数値(0.1や0.02など)は初期値になります。

エキスパート設定で上の画面のようにでてくるのでここで変更できるようになります。

メイン部分の基礎

それでは大事なメイン部分を見ていきましょう。

注意

基本的な部分は別ページにて細かい説明を行い、このページは使用している関数について主に解説します。。

その都度リンクを貼ります。

関数作成

関数とは、一定の処理を実行する流れをまとめたものです。

詳しくはこちらの記事にて(現在作成中)

if文、for文

if文とは、条件が満たされた場合に、一定の処理を実行させるために使用します。

for文とは、一定の処理を繰り返して実行させるために使用します。

EA作成において確実に使う知識です。しっかり身につけましょう。

詳しくは こちらの記事にて(現在作成中)

配列

配列とは、簡単に言うと複数の値を1つの変数にまとめて使用するためのものです。

詳しくは こちらの記事にて(現在作成中)

オープンポジションを計算する

オープンポジション(所有しているポジション)の計算をしています。
CalculateCurrentOrders()という関数を作って
OrderSelect()で所有ポジションがあるか調べ、OrderSymbol()で通貨ペアとマジックナンバーが一致しているか調べて、買いならbuysの値を増やし、売りならsellsの値を増やしてマイナスをかけています。

//+------------------------------------------------------------------+
//| Calculate open positions                                         |
//+------------------------------------------------------------------+
int CalculateCurrentOrders(string symbol)
  {
   int buys=0,sells=0;
//---
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
        {
         if(OrderType()==OP_BUY)  buys++;
         if(OrderType()==OP_SELL) sells++;
        }
     }
//--- return orders volume
   if(buys>0) return(buys);
   else       return(-sells);
  }

注文総数 OrdersTotal()

エントリー中の注文と保留中注文の総数を返します。

例えば、エントリー中のポジション数が1、保留中の指値数が1

あったとすると戻り値は2になります。

ポジションの情報を取得 OrderSelect()

OrderSelect関数では3つの引数を指定して、該当のオーダーを選択します。
オーダーの選択に成功した場合はtrue、失敗した場合はfalseが返り値となります。

MEMO

OrderSelect関数でオーダーを選択すると、OrderMagicNumberやOrderOpenPriceなどの関数を使用してオーダーの詳細情報を取得できるようになります。

基本のコードは以下になります。

bool  OrderSelect(
   int     index,            // index or order ticket
   int     select,           // flag
   int     pool=MODE_TRADES  // mode
   );
  • index
    注文インデックスを指定。
    select = SELECT_BY_TICKETの時はチケット番号を指定。
  • select
    SELECT_BY_POS : 注文プールのインデックスをindexに指定。SELECT_BY_TICKET : チケット番号をindexに指定。
  • pool
    注文プールの選択。初期値はMODE_TRADES
    select = SELECT_BY_POSの時に使用します。
    MODE_TRADES : 取引プールから注文を選択します(エントリー中の注文、保留中の注文)。
    MODE_HISTORY : 履歴プールから注文を選択します(決済済み注文・キャンセルした注文)。
注意

indexの番号は1からではなく0からです。
これは配列などと同じ感じです。 プログラミングでは数の始まりが基本的に0からです。

通貨ペア名 OrderSymbol()

現在選択中の注文の通貨ペア名を返します

事前にOrderSelect()で対象とする注文を選択する必要があります。

マジックナンバー OrderMagicNumber()

現在選択中の注文のマジックナンバーを返します 。

こちらも事前にOrderSelect()で対象とする注文を選択する必要があります。

OrderSelect()の後に使う関数一覧

OrderTicket();       //選択した注文のチケット番号                           
OrderOpenTime();     //選択した注文の注文時間                   
OrderOpenPrice();    //選択した注文の注文価格                      
OrderType();         //選択した注文の注文タイプ              
OrderLots();         //選択した注文のロット数                
OrderSymbol();       //選択した注文の通貨ペア                   
OrderStopLoss();     //選択した注文のストップロス価格               
OrderTakeProfit();   //選択した注文のリミット価格                  
OrderCloseTime();    //選択した注文の決済時間                     
OrderClosePrice();   //選択した注文の決済価格                     
OrderCommission();   //選択した注文の手数料                       
OrderExpiration();   //選択した注文の保留有効期限                  
OrderSwap();         //選択した注文のスワップ               
OrderProfit();       //選択した注文の損益                      
OrderComment();      //選択した注文のコメント                  
OrderMagicNumber();  //選択した注文のマジックナンバー 

ロットサイズの計算

このコードではロットサイズの計算をしています。
HistoryTotal()でクローズした注文数の値を取り出してます。
AccountFreeMargin()で余剰証拠金額を取得します。
それに最初に設定したMaximumRiskをかけて1000で割ったものの小数点第1位までを求めています。
lossesで負けたトレードの数をカウントして負けるとロット数を減らすようにしています。
0.1より小さいときは0.1にしています。

//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double lot=Lots;
   int    orders=HistoryTotal();     // history orders total
   int    losses=0;                  // number of losses orders without a break
//--- select lot size
   lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/1000.0,1);
//--- calcuulate number of losses orders without a break
   if(DecreaseFactor>0)
     {
      for(int i=orders-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false)
           {
            Print("Error in history!");
            break;
           }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL)
            continue;
         //---
         if(OrderProfit()>0) break;
         if(OrderProfit()<0) losses++;
        }
      if(losses>1)
         lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//--- return lot size
   if(lot<0.1) lot=0.1;
   return(lot);
  }

クローズした注文数 HistoryTotal()

OrdersHistoryTotal()の昔の関数です。

ターミナルにロードされたアカウント履歴の決済済みの注文の数を返します。

小数点第何位まで求める NormalizeDouble()

指定された精度で丸められた浮動小数点数を返します。

基本のコードは以下です。

double  NormalizeDouble(
   double  value,      // 値
   int     digits      // 丸める小数点以下の桁数
   );

今回はdigitsが1なので 小数点第1位までです。

余剰証拠金 AccountFreeMargin()

現在アカウントの余剰証拠金を返します。

ポジションを持つときの状態を確認

CheckForOpen()という関数を作ってポジションを持つときの状態を確認します。
Volume[0]>1というのは新しい足にティック数がある場合を指します。この時はreturnで戻っているので新しい足にティック数がある場合はトレードしない。
したがって、新しい足ができた直後トレードするようになっています。
iMA()関数は移動平均線の関数でそれが
Open[1](一つ前の足の始値)より小さくかつClose[1](一つ前の足の終値)より大きい、つまり移動平均線を価格が下に抜けた場合に売り注文をだします。
その逆なら買い注文を出します。
注文はOrderSend()関数を使います。

//+------------------------------------------------------------------+
//| Check for open order conditions                                  |
//+------------------------------------------------------------------+
void CheckForOpen()
  {
   double ma;
   int    res;
//--- go trading only for first tiks of new bar
   if(Volume[0]>1) return;
//--- get Moving Average 
   ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//--- sell conditions
   if(Open[1]>ma && Close[1]<ma)
     {
      res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red);
      return;
     }
//--- buy conditions
   if(Open[1]<ma && Close[1]>ma)
     {
      res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue);
      return;
     }
//---
  }

iMA()

基本のコードは以下です。

double  iMA(
   string       symbol,       // 通貨ペア
   int          timeframe,    // 時間軸
   int          ma_period,    // MAの平均期間
   int          ma_shift,     // MAシフト
   int          ma_method,    // MAの平均化メソッド
   int          applied_price,// 適用価格
   int          shift         // シフト
   );
  • string symbol
    移動平均線の値を計算する通貨ペア名を指定します。
    特定の通貨ペア名を指定せず、EAを適用したチャートの通貨ペアの場合は、「NULL」とします。
  • int timeframe
    移動平均線の値を計算する時間軸を指定。
    種 類
    定 数
    内 容
    PERIOD_CURRENT
    現在の時間足
    PERIOD_M1
    1分足
    PERIOD_M5
    5分足
    PERIOD_M15
    15
    15分足
    PERIOD_M30
    30
    30分足
    PERIOD_H1
    60
    1時間足
    PERIOD_H4
    240
    4時間足
    PERIOD_D1
    1440
    日 足
    PERIOD_W1
    10080
    週 足
    PERIOD_MN1
    43200
    月 足
  • int ma_period
    移動平均線の値を計算する期間を指定。
  • int ma_shift
    移動平均線の表示を右方向にシフト(ずらす)するバーの個数を指定。
  • int ma_method
    移動平均線の種類を指定。
    種 類
    定 数
    内 容
    MODE_SMA
    単純移動平均線
    MODE_EMA
    指数移動平均線
    MODE_SMMA
    平滑移動平均線
    MODE_LWMA
    線形加重移動平均線
  • int applied_price
    移動平均線の値の計算に使用する価格データを指定します。
    種 類
    定 数
    内 容
    PRICE_CLOSE
    終 値
    PRICE_OPEN
    始 値
    PRICE_HIGH
    高 値
    PRICE_LOW
    安 値
    PRICE_MEDIAN
    中央値
    (高値+安値)÷2
    PRICE_TYPICAL
    代表値
    (高値+安値+終値)÷3
    PRICE_WEIGHTED
    加重終値
    (高値+安値+終値+終値)÷4
  • int shift
    移動平均線の値を取得したいバーの位置を指定。
    移動平均線の値を取得したいバーが現在のバーであれば「0」とします。

オーダーをする OrderSend()

オーダー関数は、以下のような定義になっています。

int  OrderSend(
   string   symbol,               // 通貨ペア名
   int      cmd,                  // 注文タイプ
   double   volume,               // ロット数
   double   price,                // 注文価格
   int      slippage,             // スリップページ
   double   stoploss,             // ストップロス価格
   double   takeprofit,           // リミット価格
   string   comment     = NULL,   // コメント
   int      magic       = 0,      // マジックナンバー(識別用)
   datetime expiration  = 0,      // 有効期限
   color    arrow_color = clrNONE // 色
   );
  • string symbol
    注文を出す通貨ペアを指定します。
    特定の通貨ペア名を指定せず、EAを適用したチャートの通貨ペアの場合は、「Symbol()」とします。
  • int cmd
    注文方法を指定します。
    種 類
    定 数
    内 容
    OP_BUY
    成行買い
    OP_SELL
    成行売り
    OP_BUYLIMIT
    指値買い
    OP_SELLLIMIT
    指値売り
    OP_BUYSTOP
    逆指値買い
    OP_SELLSTOP
    逆指値売り
  • double volume
    ロットサイズを指定。
  • double price
    注文価格を指定。
  • int slippage
    許容スリッページ数を指定。
  • double stoploss
    損切り価格を指定。損切り価格を指定しない場合は0。
  • double takeprofit
    利益確定価格を指定。利益確定価格を指定しない場合は0。
  • string comment
    注文に対するコメントを指定。コメントを指定しない場合は、「NULL」とします。
  • int magic
    マジックナンバー(=個々のEAを識別する整数値)を指定。
  • datetime expiration
    注文の有効期限を指定。
    有効期限の指定は、待機注文に対してのみ有効です。
    有効期限を指定しない場合は0。
  • color arrow_color
    オブジェクトの表示色を指定。
    オブジェクトを表示させたくない場合は省略するか「clr_NONE」とします。

ポジションを決済するときの状態を確認

CheckForClose()という関数を作ってポジションを決済するときの状態を確認しています。
買い注文のポジションを持っている場合は、移動平均線が1つ前の足の始値より小さくかつ終値より大きい場合、つまり移動平均線を価格が下に抜けた場合に決済されます。

//+------------------------------------------------------------------+
//| Check for close order conditions                                 |
//+------------------------------------------------------------------+
void CheckForClose()
  {
   double ma;
//--- go trading only for first tiks of new bar
   if(Volume[0]>1) return;
//--- get Moving Average 
   ma=iMA(NULL,0,MovingPeriod,MovingShift,MODE_SMA,PRICE_CLOSE,0);
//---
   for(int i=0;i<OrdersTotal();i++)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
      //--- check order type 
      if(OrderType()==OP_BUY)
        {
         if(Open[1]>ma && Close[1]<ma)
           {
            if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,White))
               Print("OrderClose error ",GetLastError());
           }
         break;
        }
      if(OrderType()==OP_SELL)
        {
         if(Open[1]<ma && Close[1]>ma)
           {
            if(!OrderClose(OrderTicket(),OrderLots(),Ask,3,White))
               Print("OrderClose error ",GetLastError());
           }
         break;
        }
     }
//---
  }

OrderClose()

基本のコードは以下です。

bool  OrderClose(
   int        ticket,      // チケット番号
   double     lots,        // ロット
   double     price,       // 決済価格
   int        slippage,    // スリップページ
   color      arrow_color  // 決済カラー
   );

これでポジションの決済を行います。

  • int ticket
    決済する注文のチケット番号を指定。
  • double lots
    決済するロットサイズを指定。
  • double price
    決済価格を指定。
  • int slippage
    許容スリッページ数を指定。
  • color arrow_color
    オブジェクトの表示色を指定します。
    オブジェクトを表示させたくない場合は省略するか「clr_NONE」とします。

メイン処理

OnTick()でティックが更新されるたびに読み込みます。
Bars<100で足の数が100未満、IsTradeAllowed()==falseでトレードができない場合は注文を出しません。
CalculateCurrentOrders(Symbol())==0)はポジションがない状態を指します。その時はCheckForOpen()の関数でポジションを取るかどうかの判定に移ります。
それ以外の時はポジションがある状態ですのでCheckForClose()関数で決済するかどうかの判定に移ります。

//+------------------------------------------------------------------+
//| OnTick function                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- check for history and trading
   if(Bars<100 || IsTradeAllowed()==false)
      return;
//--- calculate open orders by current symbol
   if(CalculateCurrentOrders(Symbol())==0) CheckForOpen();
   else                                    CheckForClose();
//---
  }
//+------------------------------------------------------------------+

メイン処理 OnTick()

ここには、EAの中身そのもの、例えば、エントリーやエグジットの条件、新規注文や決済注文の命令などの各種処理を記述します。

OnTickは、チャートにレートが配信されるタイミングで実行します。

基本的に、プログラムは、上から順に動作していくので、イベントを起こしたい順番に上から記述していきます。

まとめ

このプログラムは
移動平均線が価格を上抜けした場合にロング、逆ならショート、
決済条件はポジションを取ったときの条件の逆というシンプルでした。

分からない単語、用語はすぐに調べる

始めの内は知らない単語だらけです。
自分も初見でこれを書いたので何もわからない状態でしたが、
調べまとめることでかなり理解できたと思います。

よくわからない単語をそのままにしておくと変な勘違いなど起きやすいです。
しっかり調べましょう。

最後にEAを作成したら必ずバックテストを行いましょう。できた!と言ってすぐ実践すると大きい損失になるかもしれませんよ。

以下にバックテストのやり方の記事を置いときます。

とりあえずバックテストはやっておいて損は無いのでしておきましょうね、、

EAのバックテスト(MT4)

コメントを残す

メールアドレスが公開されることはありません。