MQL5でEA開発 66 高安でトレーリングストップを実行する関数
高安でトレーリングストップを実行する関数
高安でトレーリングストップを実行する関数を作ります。
買いポジションなら直近安値に、売りポジションなら直近高値+スプレッドにストップを置きます。
名前はTrailingStopHL関数とします。
戻り値はありません。
引数は
第1引数:足の種類。ENUM_TIMEFRAMES型
第2引数:計算期間。int型
第3引数:シフト。int型
第4引数:スプレッド(価格単位)。double型
第5引数:注文間隔(ミリ秒)。int型
第6引数:マジックナンバー。int型
とします。
関数の作成にあたって、以下の定義済み変数、関数、メソッドを使用しました。
_Point
Sleep関数
SymbolInfoDouble関数
SymbolInfoInteger関数
PositionsTotal関数
PositionGetSymbol関数
PositionGetDouble関数
PositionGetInteger関数
PositionModifyメソッド
DC関数
自作関数のDC関数も使用します。
関数のコード
void TrailingStopHL(ENUM_TIMEFRAMES timeframe, int period, int shift, double spread, int order_interval, int magic)
{
/*
timeframe:足の種類
period:計算期間
shift:シフト
spread:スプレッド(価格単位)
order_interval:注文間隔(ミリ秒)
magic:マジックナンバー
*/
double new_sl=0.0; // 新しいストップ
double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); // ASK
double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); // BID
long stops_level=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL); // ストップレベル
int positions_total=PositionsTotal(); // ポジション数
//--- リスト内番号の大きい順、つまりポジションの新しい順に検索し、新しいもののみ処理する
for(int i=positions_total-1; i>=0; i--)
{
string position_symbol=PositionGetSymbol(i); // ポジションの銘柄
long position_magic=PositionGetInteger(POSITION_MAGIC); // ポジションのマジックナンバー
long position_type=PositionGetInteger(POSITION_TYPE); // ポジションのタイプ
long position_ticket=PositionGetInteger(POSITION_TICKET); // ポジションのチケット番号
double position_sl=PositionGetDouble(POSITION_SL); // ポジションのストップ
double position_tp=PositionGetDouble(POSITION_TP); // ポジションのリミット
if(position_symbol==_Symbol && position_magic==magic)
{
//--- 買いポジションの場合
if(position_type==POSITION_TYPE_BUY)
{
new_sl=DC(_Symbol,timeframe,period,2,shift)-_Point;
if(new_sl>=position_sl+_Point && new_sl<=bid-stops_level*_Point) // 前の条件は1ポイント加えないと同値になることがある
{
ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
Sleep(order_interval); // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
return;
}
}
//--- 売りポジションの場合
if(position_type==POSITION_TYPE_SELL)
{
new_sl=DC(_Symbol,timeframe,period,1,shift)+spread+_Point;
if((new_sl<=position_sl-_Point || position_sl==0.0) && new_sl>=ask+stops_level*_Point) // 前の条件は1ポイント減じないと同値になることがある
{
ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
Sleep(order_interval); // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
return;
}
}
}
}
}
この関数では直近高安をサポート、レジスタンスとしてストップを移動していますが、これを雛型にして移動平均線、ボリンジャーバンド、一目均衡表などでトレーリングストップを実行する関数を作ることもできるでしょう。
サンプルコード
#include <Trade\Trade.mqh>
CTrade ExtTrade;
double DC(string symbol, ENUM_TIMEFRAMES timeframe, int period, int mode, int shift)
/*
symbol:銘柄
timeframe:足の種類
period:計算期間
mode:モード
shift:シフト
*/
{
double res=0.0; // 戻り値
/*
mode
0:最高値と最安値の中間値
1:最高値
2:最安値
*/
//--- 最高値と最安値の中間値
if(mode==0)
{
int highest=iHighest(symbol,timeframe,MODE_HIGH,period,shift); // 最高値の位置
int lowest=iLowest(symbol,timeframe,MODE_LOW,period,shift); // 最安値の位置
double upper=iHigh(symbol,timeframe,highest); // 最高値
double lower=iLow(symbol,timeframe,lowest); // 最安値
res=(upper+lower)/2.0; // 最高値と最安値の中間値
}
//--- 最高値
if(mode==1)
{
int highest=iHighest(symbol,timeframe,MODE_HIGH,period,shift); // 最高値の位置
res=iHigh(symbol,timeframe,highest); // 最高値
}
//--- 最安値
if(mode==2)
{
int lowest=iLowest(symbol,timeframe,MODE_LOW,period,shift); // 最安値の位置
res=iLow(symbol,timeframe,lowest); // 最安値
}
return(res);
}
void TrailingStopHL(ENUM_TIMEFRAMES timeframe, int period, int shift, double spread, int order_interval, int magic)
{
/*
timeframe:足の種類
period:計算期間
shift:シフト
spread:スプレッド(価格単位)
order_interval:注文間隔(ミリ秒)
magic:マジックナンバー
*/
double new_sl=0.0; // 新しいストップ
double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK); // ASK
double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID); // BID
long stops_level=SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL); // ストップレベル
int positions_total=PositionsTotal(); // ポジション数
//--- リスト内番号の大きい順、つまりポジションの新しい順に検索し、新しいもののみ処理する
for(int i=positions_total-1; i>=0; i--)
{
string position_symbol=PositionGetSymbol(i); // ポジションの銘柄
long position_magic=PositionGetInteger(POSITION_MAGIC); // ポジションのマジックナンバー
long position_type=PositionGetInteger(POSITION_TYPE); // ポジションのタイプ
long position_ticket=PositionGetInteger(POSITION_TICKET); // ポジションのチケット番号
double position_sl=PositionGetDouble(POSITION_SL); // ポジションのストップ
double position_tp=PositionGetDouble(POSITION_TP); // ポジションのリミット
if(position_symbol==_Symbol && position_magic==magic)
{
//--- 買いポジションの場合
if(position_type==POSITION_TYPE_BUY)
{
new_sl=DC(_Symbol,timeframe,period,2,shift)-_Point;
if(new_sl>=position_sl+_Point && new_sl<=bid-stops_level*_Point) // 前の条件は1ポイント加えないと同値になることがある
{
ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
Sleep(order_interval); // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
return;
}
}
//--- 売りポジションの場合
if(position_type==POSITION_TYPE_SELL)
{
new_sl=DC(_Symbol,timeframe,period,1,shift)+spread+_Point;
if((new_sl<=position_sl-_Point || position_sl==0.0) && new_sl>=ask+stops_level*_Point) // 前の条件は1ポイント減じないと同値になることがある
{
ExtTrade.PositionModify(position_ticket,new_sl,position_tp);
Sleep(order_interval); // 短時間に注文を繰り返すことを避けるため、一定時間スリープする
return;
}
}
}
}
}
void OnTick()
{
TrailingStopHL(PERIOD_D1,10,0,0.006,60000,20248);
}
自作関数のDC関数も使用しているので、DC関数の定義もコードに書き込みます。
実行
まだポジションがないので、このコードを実行しても何も起きません。
仮に150.000円で売ったポジションがあり、マジックナンバーが20248だったとします。
そして、152.000円にストップが置いてあるとします。
もし、当日を含む直近10日高値が151.993円になったとします。
売りポジションの決済はASKで行われるので、スプレッドを加えます。
想定するスプレッド0.006円を足すと151.999円です。
すると、152.000円より低いのでストップは151.999円に移動します。