一般的なトレイリングストップに階段型を追加
一般的なトレイリングストップ関数をご覧になった読者の方から、「複雑なトレイリングストップ」に興味があるというコメントをいただきました。
複雑という言い方が適切でなく、無闇に期待値を上げてしまったのは反省です。複雑というか応用です。通常のトレイリングストップは、一定ラインを超えたら、それ以降は1ティック順行するたびに、損切り値を更新するかと思います。
でも、それって時と場合によっては、損切りに引っかかりやすくなって使いにくいこともあります。
それを回避する1つの方法に階段型が考えられます。階段型というのは、特定の値幅だけ順行したら損切り値を更新するというものです。常に更新し続ける一般型に対して、一定の値幅の単位で更新するのが階段型です。
一般的なトレイリングストップ関数とは別に関数を用意する必要があるかなぁと思っていたのですが、一般的なトレイリングストップ関数の中に包められることが分かりました。まぁ、分かりましたって言うか、プログラミングしてたら「一緒にできるじゃん!」って気づいただけなんですけどね。
というわけで階段型の関数をご紹介します。
//+------------------------------------------------------------------+
//|【関数】一般的なトレイリングストップ改良版 |
//| |
//|【引数】 IN OUT 引数名 説明 |
//| --------------------------------------------------------- |
//| ○ aMagic マジックナンバー |
//| ○ aTS_StartPips トレイリングストップ開始値幅(pips) |
//| ○ aTS_StopPips 損切り値幅(pips) |
//| △ aTS_StepPips 損切り値変更間隔(pips) |
//| |
//|【戻値】なし |
//| |
//|【備考】△:既定値あり |
//| 仕掛け位置からaTS_StartPips順行したら、その位置から |
//| aTS_StopPips逆行した位置に損切り値を設定。 |
//| それ以降は、aTS_StepPips順行するごとに損切り値を再設定。 |
//+------------------------------------------------------------------+
void trailingStopGeneral(int aMagic, double aTS_StartPips, double aTS_StopPips, double aTS_StepPips = 0.0)
{
for(int i = 0; i < OrdersTotal(); i++){
// オーダーが1つもなければ処理終了
if(OrderSelect(i, SELECT_BY_POS) == false){
break;
}
string oSymbol = OrderSymbol();
// 別EAのオーダーはスキップ
if(oSymbol != Symbol() || OrderMagicNumber() != aMagic){
continue;
}
int oType = OrderType();
// 待機オーダーはスキップ
if(oType != OP_BUY && oType != OP_SELL){
continue;
}
double digits = MarketInfo(oSymbol, MODE_DIGITS);
double oPrice = NormalizeDouble(OrderOpenPrice(), digits);
double oStopLoss = NormalizeDouble(OrderStopLoss(), digits);
int oTicket = OrderTicket();
double start = aTS_StartPips * gPipsPoint;
double stop = aTS_StopPips * gPipsPoint;
double step = aTS_StepPips * gPipsPoint;
if(oType == OP_BUY){
double price = MarketInfo(oSymbol, MODE_BID);
double modifyStopLoss = price - stop;
if(price >= oPrice + start){
if(modifyStopLoss > oStopLoss){
if(MathAbs(modifyStopLoss - oStopLoss) >= step){
orderModifyReliable(oTicket, 0.0, modifyStopLoss, 0.0, 0, gArrowColor[oType]);
}
}
}
}else if(oType == OP_SELL){
price = MarketInfo(oSymbol, MODE_ASK);
modifyStopLoss = price + stop;
if(price <= oPrice - start){
// ショートの場合、条件式にoStopLoss == 0.0が必要
// oStopLoss = 0.0の場合、modifyStopLossには価格(正の値)が格納されるため、
// modifyStopLoss < oStopLossの条件が永久に成立しなくなるため
if(modifyStopLoss < oStopLoss || oStopLoss == 0.0){
if(MathAbs(modifyStopLoss - oStopLoss) >= step){
orderModifyReliable(oTicket, 0.0, modifyStopLoss, 0.0, 0, gArrowColor[oType]);
}
}
}
}
}
}
一般的なトレイリング関数と見比べると分かると思いますが、殆ど手を加えていません。主要な変更箇所は、損切り値の更新の条件に「if(MathAbs(modifyStopLoss – oStopLoss) >= step){」を追加し、関数の引数に「double aTS_StepPips = 0.0」を追加したぐらいです。
「double aTS_StepPips = 0.0」と引数に初期値を持たせることで、この関数を呼び出す時にこの引数を省略することが可能になります。何が言いたいかというと、従来の一般的なトレイリングストップ関数を使っていて、別に階段型にする必要がない場合は、何も変更しなくても大丈夫ということです。
上記の階段型以外にも、ATRやある期間の最高値/最安値を使って損切り値を更新する方法があります。別途ご紹介する予定です。
はたまた、仕掛けてから一定時間経過したら強制的に損切り値を更新するとか、一定値幅の利益を確保できたら半分だけ決済して、残りを継続してトレイリングするといったことも可能です。これまでご紹介したテクニックを応用すれば、これらのことも実現できるはずです。ぜひ、チャレンジしてみてください。
