カスタムインジケータソースコード全体
カスタムインジケータとして、移動平均線で、短期と長期の2本を表示して、クロスしたときに売りシグナル(デッドクロス)、買いシグナル(ゴールデンクロス)を表示するインジケータをまず作ります。
//+------------------------------------------------------------------+
//| FXind_moving_average.mq4|
//| Copyright (c) 2021, Langtainment |
//| https://tsunagaru-info.com/dr |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2021, Langtainment"
#property link "https://tsunagaru-info.com/dr"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_color3 Blue
#property indicator_color4 Red
//Unique Parameters
extern int FastMA_Period = 10; //Parameter 1
extern int SlowMA_Period = 40; //Parameter 2
//indicator Buffers
double BufFastMA[];
double BufSlowMA[];
double BufBuy[];
double BufSell[];
//+-----------------------------------------------------------------------------------------------------------------------------+
//| |
//| Onnit() works at the time of EA application, time step change, property change, and MT4 restart, as initialization process. |
//| |
//+-----------------------------------------------------------------------------------------------------------------------------+
int OnInit()
{
//allocate indicator buffer
SetIndexBuffer(0, BufFastMA);
SetIndexBuffer(1, BufSlowMA);
SetIndexBuffer(2, BufBuy);
SetIndexBuffer(3, BufSell);
//Setting Indicator Label
SetIndexLabel(0,"FastMA("+FastMA_Period+")");
SetIndexLabel(1,"SlowMA("+SlowMA_Period+")");
SetIndexLabel(2,"BuySignal");
SetIndexLabel(3,"SellSignal");
//Setting Indicator Style (Buy Signal)
SetIndexStyle(2, DRAW_ARROW, STYLE_SOLID, 1, Blue);
SetIndexArrow(2,233);
//Setting indicator style (Sell signal)
SetIndexStyle(3, DRAW_ARROW, STYLE_SOLID, 1, Red);
SetIndexArrow(3,234);
return(0);
}
//+--------------------------------------------------------------------------------------------------------------------------------------+
//| |
//| OnCalculate() works at the timing when the rate of the currency pair on the chart you applied is delivered, as the main processing. |
//| |
//+--------------------------------------------------------------------------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
int i; //counter
int end_index = Bars - prev_calculated; // Get bar count (uncalculated)
if (prev_calculated == 0) end_index -= SlowMA_Period-1;
for(i = end_index -1 ; i >=0 ; i-- ) {
//Fast Moving Average
BufFastMA[i] = iMA(
NULL, // Currency Pair
0, // time axis
FastMA_Period, // MA average period
0, // MA Shift
MODE_SMMA, // MA averaging method
PRICE_CLOSE, // Applicable price
i // Shift
);
//Slow Moving Average
BufSlowMA[i] = iMA(
NULL, // Currency Pair
0, // time axis
SlowMA_Period, // MA average period
0, // MA Shift
MODE_SMMA, // MA averaging method
PRICE_CLOSE, // Applicable price
i // Shift
);
}
if (prev_calculated == 0) end_index -= 2;
for(i = end_index -1 ; i >=0 ; i-- )
{
//Buy Signal
BufBuy[i] = EMPTY_VALUE;
if(BufFastMA[i+2] <= BufSlowMA[i+2] && BufFastMA[i+1] > BufSlowMA[i+1])
{
BufBuy[i] = Open[i];
}
//Sell Signal
BufSell[i] = EMPTY_VALUE;
if(BufFastMA[i+2] >= BufSlowMA[i+2] && BufFastMA[i+1] < BufSlowMA[i+1])
{
BufSell[i] = Open[i];
}
}
//Return value setting: passed to the value of prev_calculated the next time the OnCalculate() is called.
return( rates_total );
}
ソースコード説明
宣言部分
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Blue ・・①
#property indicator_color2 Red ・・②
#property indicator_color3 Blue ・・③
#property indicator_color4 Red ・・④
//Unique Parameters
extern int FastMA_Period = 10; //Parameter 1
extern int SlowMA_Period = 40; //Parameter 2
//indicator Buffers
double BufFastMA[]; ・・①
double BufSlowMA[]; ・・②
double BufBuy[]; ・・③
double BufSell[]; ・・④
- 短期移動平均線
- 長期移動平均線
- 買いシグナル
- 売りシグナル
初期化部分
int OnInit()
{
//allocate indicator buffer
SetIndexBuffer(0, BufFastMA);
SetIndexBuffer(1, BufSlowMA);
SetIndexBuffer(2, BufBuy);
SetIndexBuffer(3, BufSell);
//Setting Indicator Label
SetIndexLabel(0,"FastMA("+FastMA_Period+")");
SetIndexLabel(1,"SlowMA("+SlowMA_Period+")");
SetIndexLabel(2,"BuySignal");
SetIndexLabel(3,"SellSignal");
//Setting Indicator Style (Buy Signal)
SetIndexStyle(2, DRAW_ARROW, STYLE_SOLID, 1, Blue);
SetIndexArrow(2,233);
//Setting indicator style (Sell signal)
SetIndexStyle(3, DRAW_ARROW, STYLE_SOLID, 1, Red);
SetIndexArrow(3,234);
return(0);
}
- 0:短期移動平均線
- 1:長期移動平均線
- 2:買いシグナル
- 3:売りシグナル
Wingdingsフォントによる絵文字一覧:Windows(ウィンドウズ)の使い方
対象:Windows全般 文字コードとWingdingsフォントによる表示結果...
メイン部分1
int OnCalculate(・・・省略・・・)
{
int i; //counter
int end_index = Bars - prev_calculated; // Get bar count (uncalculated)
if (prev_calculated == 0) end_index -= SlowMA_Period-1;
for(i = end_index -1 ; i >=0 ; i-- ) {
//Fast Moving Average
BufFastMA[i] = iMA(
NULL, // Currency Pair
0, // time axis
FastMA_Period, // MA average period
0, // MA Shift
MODE_SMMA, // MA averaging method
PRICE_CLOSE, // Applicable price
i // Shift
);
//Slow Moving Average
BufSlowMA[i] = iMA(
NULL, // Currency Pair
0, // time axis
SlowMA_Period, // MA average period
0, // MA Shift
MODE_SMMA, // MA averaging method
PRICE_CLOSE, // Applicable price
i // Shift
);
}
・・・省略・・・
}
メイン部分2
int OnCalculate(・・・省略・・・)
{
・・・省略・・・
if (prev_calculated == 0) end_index -= 2;
for(i = end_index -1 ; i >=0 ; i-- )
{
//Buy Signal
BufBuy[i] = EMPTY_VALUE;
if(BufFastMA[i+2] <= BufSlowMA[i+2] && BufFastMA[i+1] > BufSlowMA[i+1])
{
BufBuy[i] = Open[i];
}
//Sell Signal
BufSell[i] = EMPTY_VALUE;
if(BufFastMA[i+2] >= BufSlowMA[i+2] && BufFastMA[i+1] < BufSlowMA[i+1])
{
BufSell[i] = Open[i];
}
}
//Return value setting: passed to the value of prev_calculated the next time the OnCalculate() is called.
return( rates_total );
}
インジケータ表示内容
表示した結果が以下です。2本の移動平均線とクロスした際に売買シグナルが矢印で表示されています。
インジケータをEA化
このインジケータを利用したEAが以下となります。利用といっても単に移動平均線を利用しているだけで、上述のインジケータを流用する必要は正直ありません。インジケータとEAをはっきり連動したいのでインジケータからEAへのインプットを渡すというのがしたいので今回このコードを書いてみました。移動平均線を利用したEAソースコード全体
//+------------------------------------------------------------------+
//| FXexp_moving_average.mq4|
//| Copyright (c) 2021, Langtainment |
//| https://tsunagaru-info.com/dr |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2021, Langtainment"
#property link "https://tsunagaru-info.com/dr"
#include <stdlib.mqh>
//Magic Number
#define MAGIC_NUMBER 20211016
//SIGNAL
#define ENTRY_BUY_SIGNAL 1
#define ENTRY_SELL_SIGNAL 2
#define CLOSE_BUY_SIGNAL 4
#define CLOSE_SELL_SIGNAL 8
//
#define REFERENCE_INDICATOR "original\FXind_moving_average"
//Common Parameters
extern double Lots = 1;
extern int Slippage = 3;
//Unique Parameters
extern int FastMA_Period = 10;
extern int SlowMA_Period = 40;
double FastMA2 = EMPTY_VALUE;
double FastMA1 = EMPTY_VALUE;
double SlowMA2 = EMPTY_VALUE;
double SlowMA1 = EMPTY_VALUE;
int ticket = 0;
int errorcode = 0;
int Adjusted_Slippage = 0;
datetime Bar_Time = 0;
bool closed = false;
//+------------------------------------------------------------------+
//| Adjust Slippage according to Number of digits after the decimal point |
//+------------------------------------------------------------------+
int AdjustSlippage(string Currency,int Slippage_Pips)
{
int Symbol_Digits = MarketInfo(Currency,MODE_DIGITS);
if(Symbol_Digits == 2 || Symbol_Digits == 4)
{
int Calculated_Slippage = Slippage_Pips;
}
else if(Symbol_Digits == 3 || Symbol_Digits == 5)
{
Calculated_Slippage = Slippage_Pips * 10;
}
else
{
//unreachable
}
return(Calculated_Slippage);
}
//+-----------------------------------------------------------------------------------------------------------------------------+
//| |
//| Oninit() works at the time of EA application, time step change, property change, and MT4 restart, as initialization process. |
//| |
//+-----------------------------------------------------------------------------------------------------------------------------+
int Oninit()
{
Adjusted_Slippage = AdjustSlippage(Symbol(),Slippage);
return(0);
}
//+------------------------------------------------------------------+
//| Calculate Current Orders |
//+------------------------------------------------------------------+
int CalculateCurrentOrders()
{
//The number of Current Orders(+:BUY -:SELL)
int pos=0;
for(int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) == false) break;
if(OrderSymbol() == Symbol() && OrderMagicNumber() == MAGIC_NUMBER)
{
if(OrderType() == OP_BUY) pos++;
if(OrderType() == OP_SELL) pos--;
}
}
return(pos);
}
//+------------------------------------------------------------------+
//| SIGNAL |
//+------------------------------------------------------------------+
int AnalyzeSignal()
{
int flags = 0;
FastMA2 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,0,2); //for FastMA_Period
SlowMA2 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,1,2); //for SlowMA_Period
FastMA1 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,0,1); //for FastMA_Period
SlowMA1 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,1,1); //for SlowMA_Period
if(FastMA2 == EMPTY_VALUE || SlowMA2 == EMPTY_VALUE || FastMA1 == EMPTY_VALUE || SlowMA1 == EMPTY_VALUE)
{
return flags;
}
if(FastMA2 >= SlowMA2 && FastMA1 < SlowMA1)
{
flags = CLOSE_BUY_SIGNAL|ENTRY_SELL_SIGNAL;
}
else if(FastMA2 <= SlowMA2 && FastMA1 > SlowMA1)
{
flags = CLOSE_SELL_SIGNAL|ENTRY_BUY_SIGNAL;
}
else
{
//no operation
}
return flags;
}
//+------------------------------------------------------------------+
//| Close Positions |
//+------------------------------------------------------------------+
void ClosePositions()
{
for(int i=0; i<OrdersTotal(); i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) == false) break;
if(OrderMagicNumber() != MAGIC_NUMBER || OrderSymbol() != Symbol()) continue;
//Check Order type
if(OrderType() == OP_BUY)
{
closed = OrderClose(OrderTicket(),OrderLots(),Bid,Adjusted_Slippage,White);
if(closed==False)
{
errorcode=GetLastError();
printf("OrderClose Error! error_code:%d , detail:%s ",errorcode,ErrorDescription(errorcode));
}
break;
}
else if(OrderType() == OP_SELL)
{
closed = OrderClose(OrderTicket(),OrderLots(),Ask,Adjusted_Slippage,White);
if(closed==False)
{
errorcode=GetLastError();
printf("OrderClose Error! error_code:%d , detail:%s ",errorcode,ErrorDescription(errorcode));
}
break;
}
else
{
//unreachable
}
}
}
//+--------------------------------------------------------------------------------------------------------------------------------------+
//| |
//| OnTick() works at the timing when the rate of the currency pair on the chart you applied is delivered, as the main processing. |
//| |
//+--------------------------------------------------------------------------------------------------------------------------------------+
void OnTick(){
//Check if allowable trade at opening-price
if(Volume[0] > 1 || IsTradeAllowed() == false)
{
return;
}
//Calculate Current Orders
int pos = CalculateCurrentOrders();
//Check signal
int signal = AnalyzeSignal();
//BUY signal
if(pos <= 0 && ((signal & ENTRY_BUY_SIGNAL) == ENTRY_BUY_SIGNAL))
{
ClosePositions();
ticket = OrderSend(Symbol(),OP_BUY,Lots,Ask,Adjusted_Slippage,0,0,"",MAGIC_NUMBER,0,Blue);
if(ticket < 0){
errorcode=GetLastError();
printf("Send Error! error_code:%d , detail:%s ",errorcode,ErrorDescription(errorcode));
}
} //SELL signal else if(pos >= 0 && ((signal & ENTRY_SELL_SIGNAL) == ENTRY_SELL_SIGNAL))
{
ClosePositions();
ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,Adjusted_Slippage,0,0,"",MAGIC_NUMBER,0,Red);
if(ticket < 0){
errorcode=GetLastError();
printf("Send Error! error_code:%d , detail:%s ",errorcode,ErrorDescription(errorcode));
}
} //Close BUY position else if(pos > 0 && ((signal & CLOSE_BUY_SIGNAL) == CLOSE_BUY_SIGNAL))
{
ClosePositions();
}
//Close SELL position
else if(pos < 0 && ((signal & CLOSE_SELL_SIGNAL) == CLOSE_SELL_SIGNAL))
{
ClosePositions();
}
else
{
//no operation
}
return;
}
- init() → Oninit()
- start() → Ontick()
シグナル計算部分
//SIGNAL //再掲
#define ENTRY_BUY_SIGNAL 1 //再掲
#define ENTRY_SELL_SIGNAL 2 //再掲
#define CLOSE_BUY_SIGNAL 4 //再掲
#define CLOSE_SELL_SIGNAL 8 //再掲
int AnalyzeSignal()
{
int flags = 0;
FastMA2 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,0,2); //for FastMA_Period
SlowMA2 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,1,2); //for SlowMA_Period
FastMA1 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,0,1); //for FastMA_Period
SlowMA1 = iCustom(NULL,0,REFERENCE_INDICATOR,FastMA_Period,SlowMA_Period,1,1); //for SlowMA_Period
if(FastMA2 == EMPTY_VALUE || SlowMA2 == EMPTY_VALUE || FastMA1 == EMPTY_VALUE || SlowMA1 == EMPTY_VALUE)
{
return flags;
}
if(FastMA2 >= SlowMA2 && FastMA1 < SlowMA1)
{
flags = CLOSE_BUY_SIGNAL|ENTRY_SELL_SIGNAL;
}
else if(FastMA2 <= SlowMA2 && FastMA1 > SlowMA1)
{
flags = CLOSE_SELL_SIGNAL|ENTRY_BUY_SIGNAL;
}
else
{
//no operation
}
return flags;
}
#define REFERENCE_INDICATOR "original\FXind_moving_average" // ヘッダに記載しているものの再掲
FastMA2 = iCustom(NULL, //通貨ペア、適用チャートに準ずる場合はNULLとする
0, //時間軸、適用チャートに準ずる場合は0とする
REFERENCE_INDICATOR, //参照するインジケータの名称
FastMA_Period, // 参照するインジケータの1番目のパラメータ
SlowMA_Period, // 参照するインジケータの2番目のパラメータ
0, // 参照するインジケータの0番目のライン
2); // 現在バーを基準にして、指定した時間軸のバー数分を過去方向へシフト
//for FastMA_Period
if(FastMA2 >= SlowMA2 && FastMA1 < SlowMA1)
{
flags = CLOSE_BUY_SIGNAL|ENTRY_SELL_SIGNAL;
}
メイン部分
void OnTick(){
//Check if allowable trade at opening-price
if(Volume[0] > 1 || IsTradeAllowed() == false)
{
return;
}
//Calculate Current Orders
int pos = CalculateCurrentOrders();
//Check signal
int signal = AnalyzeSignal();
//BUY signal
if(pos <= 0 && ((signal & ENTRY_BUY_SIGNAL) == ENTRY_BUY_SIGNAL))
{
ClosePositions();
ticket = OrderSend(Symbol(),OP_BUY,Lots,Ask,Adjusted_Slippage,0,0,"",MAGIC_NUMBER,0,Blue);
if(ticket < 0){ errorcode=GetLastError(); printf("Send Error! error_code:%d , detail:%s ",errorcode,ErrorDescription(errorcode)); } } //SELL signal else if(pos >= 0 && ((signal & ENTRY_SELL_SIGNAL) == ENTRY_SELL_SIGNAL))
{
ClosePositions();
ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,Adjusted_Slippage,0,0,"",MAGIC_NUMBER,0,Red);
if(ticket < 0){ errorcode=GetLastError(); printf("Send Error! error_code:%d , detail:%s ",errorcode,ErrorDescription(errorcode)); } } //Close BUY position else if(pos > 0 && ((signal & CLOSE_BUY_SIGNAL) == CLOSE_BUY_SIGNAL))
{
ClosePositions();
}
//Close SELL position
else if(pos < 0 && ((signal & CLOSE_SELL_SIGNAL) == CLOSE_SELL_SIGNAL))
{
ClosePositions();
}
else
{
//no operation
}
return;
}
コメント