#property copyright "Tono" #define SIGNAL_NONE 0 #define SIGNAL_BUY 1 #define SIGNAL_SELL 2 #define SIGNAL_CLOSEBUY 3 #define SIGNAL_CLOSESELL 4 #define DTO_SK 0 #define DTO_SD 1 extern bool AllowAutoTrade = False; int FirstStopLossBarCount = 34; extern string LongTimeFrame = "D1"; extern int LongPattern = 1; int LongPeriodRSI =8; int LongPeriodStoch= 5; int LongPeriodSK = 3; int LongPeriodSD = 3; int LongMAMode = 0; extern string ShortTimeFrame = "H4"; extern int ShortPattern = 1; int ShortPeriodRSI =8; int ShortPeriodStoch= 5; int ShortPeriodSK = 3; int ShortPeriodSD = 3; int ShortMAMode = 0; extern int MagicNumber = 12345; extern double Risk = 1; extern int Slippage = 5; int BarCount; int Current; bool TickCheck = False; bool SignalMail = True; bool EachTickMode = False; int LongTimeFrameInt = 1440; int ShortTimeFrameInt =240; int Order = 0; int LotDigits; bool IsTrading = False; string title; string message; double LongSK; double LongSD; double ShortSK_now; double ShortSD_now; double ShortSK_before; double ShortSD_before; int i = 0; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { BarCount = Bars - 1; if (EachTickMode) Current = 0; else Current = 1; LongPeriodRSI =8; LongPeriodStoch= 5; LongPeriodSK = 3; LongPeriodSD = 3; ShortPeriodRSI =8; ShortPeriodStoch= 5; ShortPeriodSK = 3; ShortPeriodSD = 3; for (int i = 0; i < LongPattern; i++) { int LongNewRSI = LongPeriodRSI + LongPeriodStoch; LongPeriodSD = LongPeriodStoch; LongPeriodSK = LongPeriodStoch; LongPeriodStoch = LongPeriodRSI; LongPeriodRSI = LongNewRSI; } for (i = 0; i < ShortPattern; i++) { int ShortNewRSI = ShortPeriodRSI + ShortPeriodStoch; ShortPeriodSD = ShortPeriodStoch; ShortPeriodSK = ShortPeriodStoch; ShortPeriodStoch = ShortPeriodRSI; ShortPeriodRSI = ShortNewRSI; } if (LongTimeFrame=="M1" || LongTimeFrame=="1") LongTimeFrameInt=PERIOD_M1; if (LongTimeFrame=="M5" || LongTimeFrame=="5") LongTimeFrameInt=PERIOD_M5; if (LongTimeFrame=="M15"|| LongTimeFrame=="15") LongTimeFrameInt=PERIOD_M15; if (LongTimeFrame=="M30"|| LongTimeFrame=="30") LongTimeFrameInt=PERIOD_M30; if (LongTimeFrame=="H1" || LongTimeFrame=="60") LongTimeFrameInt=PERIOD_H1; if (LongTimeFrame=="H4" || LongTimeFrame=="240") LongTimeFrameInt=PERIOD_H4; if (LongTimeFrame=="D1" || LongTimeFrame=="1440") LongTimeFrameInt=PERIOD_D1; if (LongTimeFrame=="W1" || LongTimeFrame=="10080") LongTimeFrameInt=PERIOD_W1; if (LongTimeFrame=="MN" || LongTimeFrame=="43200") LongTimeFrameInt=PERIOD_MN1; if (LongTimeFrameInt= 2) { MailOrPrint("Error: " + Symbol() + " too many tickets ", "ticket count : " + TicketCount); break; } Tickets[TicketCount] = OrderTicket(); TicketCount = TicketCount + 1; } } if (TicketCount == 1) { modifyLongTicket(Tickets[0]); } else if (TicketCount == 2) { modifyWhenTwoTicket(Tickets); } if (IsTrading && !IsTrade) { MailOrPrint("Order closed: " + Symbol(), "Order closed: " + Symbol()); } return(IsTrade); } /** * 2つのチケットがある場合(注文中もしくは短期ポジ持ち)に注文を修正します。 */ void modifyWhenTwoTicket(int Tickets[]) { double StopLossLevel, OpenLevel; for (int i = 0; i < 2; i++) { OrderSelect(Tickets[i], SELECT_BY_TICKET, MODE_TRADES); if(OrderType() == OP_BUY) { if(isTrailShortTimeFramePosition()) { StopLossLevel = Low[1] - Point * Slippage; if(OrderStopLoss() < StopLossLevel) { OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel, OrderTakeProfit(), 0, MediumSeaGreen); } } // 1つだけ break; } else if (OrderType() == OP_SELL) { if(isTrailShortTimeFramePosition()) { StopLossLevel = High[1] + Point * Slippage; if(OrderStopLoss() > StopLossLevel) { OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel , OrderTakeProfit(), 0, DarkOrange); } } // 1つだけ break; } else if (OrderType() == OP_BUYSTOP) { if(LongSK > LongSD && ShortSK_now > ShortSD_now) { OpenLevel = High[1] + Point; StopLossLevel = Low[iLowest(NULL, ShortTimeFrameInt, MODE_LOW, FirstStopLossBarCount, 1)] - Point; if(OrderOpenPrice() > OpenLevel) { OrderModify(OrderTicket(), OpenLevel, StopLossLevel , OrderTakeProfit(), 0, MediumSeaGreen); } } else { OrderDelete(OrderTicket()); } } else if (OrderType() == OP_SELLSTOP) { if(LongSK < LongSD && ShortSK_now < ShortSD_now) { OpenLevel = Low[1] - Point; StopLossLevel = High[iHighest(NULL, ShortTimeFrameInt, MODE_HIGH, FirstStopLossBarCount, 1)] + Point; if(OrderOpenPrice() < OpenLevel) { OrderModify(OrderTicket(), OpenLevel, StopLossLevel, OrderTakeProfit(), 0, DarkOrange); } } else { OrderDelete(OrderTicket()); } } } } /** * 短期ポジションのストップを動かすべきかを調べます。 * 短期DTオシレーターが2回逆方向へクロスしたかどうかで判定します。(ABC調整パターン形成完了後の反転) */ bool isTrailShortTimeFramePosition(){ int OpenBar = iBarShift(NULL, ShortTimeFrameInt, OrderOpenTime()); int ClossCount = 0; bool Res = False; double SK_now, SD_now, SK_before, SD_before = 0.0; for (int i = OpenBar; i >= 0; i--) { SK_before = SK_now; SD_before = SD_now; SK_now = iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode,0, i); SD_now = iCustom(NULL, 0, "DT Oscillator", ShortTimeFrame, ShortPeriodRSI, ShortPeriodStoch, ShortPeriodSK, ShortPeriodSD, ShortMAMode, 1, i); if ((OrderType() == OP_BUY && SK_before > SD_before && SK_now < SD_now) || (OrderType() == OP_SELL && SK_before < SD_before && SK_now > SD_now)) { ClossCount = ClossCount + 1; } if (ClossCount >= 2) { Res = True; break; } } return(Res); } /** * 長期ポジションのストップを移動します。 */ void modifyLongTicket(int TicketNo) { double StopLossLevel, OpenLevel; OrderSelect(TicketNo, SELECT_BY_TICKET, MODE_TRADES); if(OrderType() == OP_BUY) { if((LongSK > 75 && LongSD > 75) || (LongSK < LongSD)) { StopLossLevel = Low[1]; if(OrderStopLoss() < StopLossLevel) { OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel, OrderTakeProfit(), 0, MediumSeaGreen); } } } else if (OrderType() == OP_SELL) { if((LongSK < 25 && LongSD < 25) || (LongSK > LongSD)) { StopLossLevel = High[1]; if(OrderStopLoss() > StopLossLevel) { OrderModify(OrderTicket(), OrderOpenPrice(), StopLossLevel , OrderTakeProfit(), 0, DarkOrange); } } } else { MailOrPrint("Error " + Symbol() + ": only one stop ticket", "ticket No : " + TicketNo); } } /** * 新規のポジションを建てます。 */ void checkNewTrade() { double OpenLevel, StopLossLevel, StopLossValue, Lots, OneLot; int Ticket, SendOrderType, ArrowColor; if (EachTickMode) TickCheck = True; //+------------------------------------------------------------------+ //| Signal Begin(Entry) | //+------------------------------------------------------------------+ if ( LongSK > LongSD && !(LongSK > 75 && LongSD > 75) && ShortSK_now > ShortSD_now && ShortSK_before< ShortSD_before) { Order = SIGNAL_BUY; } if ( LongSK < LongSD && !(LongSK < 25 && LongSD < 25) && ShortSK_now < ShortSD_now && ShortSK_before> ShortSD_before) { Order = SIGNAL_SELL; } //+------------------------------------------------------------------+ //| Signal End | //+------------------------------------------------------------------+ if (Order == SIGNAL_BUY) { OpenLevel = High[1] + Slippage * Point; StopLossLevel = Low[iLowest(NULL, ShortTimeFrameInt, MODE_LOW, FirstStopLossBarCount, 1)] - Point; // ストップロスが近すぎる場合は設置可能な最低限の場所へ移動 if ((Bid - StopLossLevel) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) { StopLossLevel = NormalizeDouble(Bid - (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point), Digits); } StopLossValue = Bid - StopLossLevel; // 逆指値が近すぎる場合は即時オープン if (OpenLevel - Ask < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) { SendOrderType = OP_BUY; OpenLevel = Ask; } else { SendOrderType = OP_BUYSTOP; } ArrowColor = DodgerBlue; } else if (Order == SIGNAL_SELL) { OpenLevel = Low[1] + Slippage * Point; StopLossLevel = High[iHighest(NULL, ShortTimeFrameInt, MODE_HIGH, FirstStopLossBarCount, 1)] + Point; // ストップロスが近すぎる場合は設置可能な最低限の場所へ移動 if ((StopLossLevel - Ask) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) { StopLossLevel = NormalizeDouble(Ask + (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point), Digits); } StopLossValue = StopLossLevel - Ask; // 逆指値が近すぎる場合は即時オープン if ((Bid - OpenLevel) < (MarketInfo(Symbol(), MODE_STOPLEVEL) * Point + Slippage * Point)) { SendOrderType = OP_SELL; OpenLevel = Bid; } else { SendOrderType = OP_SELLSTOP; } ArrowColor = DeepPink; } else { return(0); } // ロット数は口座残高のリスク%÷1ロット分ストップロスにかかった場合の口座通過における損失額(ストップロス価格差×1ティックの口座通貨における金額) Lots = NormalizeDouble((AccountBalance() * (Risk / 100.0)) / ((StopLossValue / MarketInfo(Symbol(), MODE_TICKSIZE)) * MarketInfo(Symbol(), MODE_TICKVALUE)), LotDigits); OneLot = NormalizeDouble((Lots / 2.0), LotDigits); //四捨五入されてしまうので、残りと比較して小さい方を選ぶ if (OneLot > (Lots - OneLot)) { OneLot = Lots - OneLot; } if (OneLot < MarketInfo(Symbol(),MODE_MINLOT)) { MailOrPrint("Error: " + Symbol() + " Lots is under minlot", "Lots:" + DoubleToStr(Lots, LotDigits) + "\nMinLot:" + MarketInfo(Symbol(),MODE_MINLOT)); return(0); } Ticket = OrderSend(Symbol(), SendOrderType, OneLot, OpenLevel, Slippage, StopLossLevel, 0, "New Order:" + MagicNumber, MagicNumber, 0, ArrowColor); checkSendOrder(Ticket); Ticket = OrderSend(Symbol(), SendOrderType, (Lots - OneLot), OpenLevel, Slippage, StopLossLevel, 0, "New Oorder:" + MagicNumber, MagicNumber, 0, ArrowColor); checkSendOrder(Ticket); return(0); } /** * 注文が通ったか確認します。 */ void checkSendOrder(int Ticket) { if(Ticket > 0) { if (OrderSelect(Ticket, SELECT_BY_TICKET, MODE_TRADES)) { string type; if (OrderType() == OP_BUYSTOP) type = "Buy"; else type = "Sell"; Print(type + " order opened : ", OrderOpenPrice()); if (SignalMail) MailOrPrint("[Signal Alert]", "[" + Symbol() + "] " + DoubleToStr(Ask, Digits) + " Open " + type); } } else { Print("Error: " + Symbol() + " opening order : ", GetLastError()); } } /** * シグナル発生を確認してメールを送信します。 */ int checkMail(){ if (!(LongSK > 75 && LongSD > 75) && ((LongSK > LongSD)) && ShortSK_before< ShortSD_before && ShortSK_now > ShortSD_now) { MakeMessageBuy(); MailAndArrow(SIGNAL_BUY, "B"); } else if (!(LongSK < 25 && LongSD < 25) && ((LongSK < LongSD)) && ShortSK_before> ShortSD_before && ShortSK_now < ShortSD_now) { MakeMessageSell(); MailAndArrow(SIGNAL_SELL, "S"); } return(0); } /** * 買いシグナルのメッセージを作成します。 */ void MakeMessageBuy() { title = "Buy Signal " + Symbol() + " " + Period(); message = "[Buy Signal]\n" + "[" + Symbol() + "] \n" + "Price:" + DoubleToStr(Ask, Digits) + "\n" + MakeHighLow(); } /** * 売りシグナルのメッセージを作成します。 */ void MakeMessageSell() { title = "Sell Signal " + Symbol() + " " + Period(); message = "[Sell Signal]\n" + "[" + Symbol() + "] \n" + "Price:" + DoubleToStr(Ask, Digits) + "\n" + MakeHighLow(); } string MakeHighLow() { string highLow = ""; for (int i = 1; i < 11; i++) { highLow = (highLow + "high" + i + ":" + High[i] + " low" + i + ":" + Low[i] + "\n"); } return (highLow); } /** * メールを送信し、直近のバーに矢印を置きます。 */ void MailAndArrow(int signal, string str) { MailOrPrint(title, message); string name = "arrow" + i; ObjectCreate(name, OBJ_TEXT, 0, Time[1], Close[1]); if (signal == SIGNAL_BUY) { ObjectSetText(name, str , 14, "Verdana", White); ObjectSet(name, OBJPROP_COLOR, Magenta); } else { ObjectSetText(name, str , 14 , "Verdana", White); ObjectSet(name, OBJPROP_COLOR, Turquoise); } i = i + 1; } /** * メールを送信します。 * テストモードの時にはPrintを行います。 */ void MailOrPrint(string ttl, string msg) { if (IsTesting()) { Print("Mailed. title:" + ttl + " message:" + msg); } else { SendMail(ttl, msg); } } /** * 売買が許可されているかを表示します。 */ void showAllowTrade() { string str = ""; int height = 10; height += 20; if (AllowAutoTrade) { str = "Auto Trading!"; ObjectCreate("AllowAutoTrade", OBJ_LABEL, 0, 0, 0); ObjectSetText("AllowAutoTrade", str, 10, "Verdana", Red); ObjectSet("AllowAutoTrade", OBJPROP_CORNER, 0); ObjectSet("AllowAutoTrade", OBJPROP_XDISTANCE, 20); ObjectSet("AllowAutoTrade", OBJPROP_YDISTANCE, height); } else { ObjectDelete("AllowAutoTade"); } } void showDebug() { string str = ""; int height = 20; height += 20; str = "LongSK: " + DoubleToStr(LongSK, 0); ObjectCreate("LongSK", OBJ_LABEL, 0, 0, 0); ObjectSetText("LongSK", str, 10, "Verdana", White); ObjectSet("LongSK", OBJPROP_CORNER, 0); ObjectSet("LongSK", OBJPROP_XDISTANCE, 20); ObjectSet("LongSK", OBJPROP_YDISTANCE, height); height += 20; str = "LongSD: " + DoubleToStr(LongSD, 0); ObjectCreate("LongSD", OBJ_LABEL, 0, 0, 0); ObjectSetText("LongSD", str, 10, "Verdana", White); ObjectSet("LongSD", OBJPROP_CORNER, 0); ObjectSet("LongSD", OBJPROP_XDISTANCE, 20); ObjectSet("LongSD", OBJPROP_YDISTANCE, height); height += 20; str = "ShortSK_now: " + DoubleToStr(ShortSK_now, 0); ObjectCreate("ShortSK_now", OBJ_LABEL, 0, 0, 0); ObjectSetText("ShortSK_now", str, 10, "Verdana", White); ObjectSet("ShortSK_now", OBJPROP_CORNER, 0); ObjectSet("ShortSK_now", OBJPROP_XDISTANCE, 20); ObjectSet("ShortSK_now", OBJPROP_YDISTANCE, height); height += 20; str = "ShortSD_now: " + DoubleToStr(ShortSD_now, 0); ObjectCreate("ShortSD_now", OBJ_LABEL, 0, 0, 0); ObjectSetText("ShortSD_now", str, 10, "Verdana", White); ObjectSet("ShortSD_now", OBJPROP_CORNER, 0); ObjectSet("ShortSD_now", OBJPROP_XDISTANCE, 20); ObjectSet("ShortSD_now", OBJPROP_YDISTANCE, height); height += 20; str = "ShortSK_before: " + DoubleToStr(ShortSK_before, 0); ObjectCreate("ShortSK_before", OBJ_LABEL, 0, 0, 0); ObjectSetText("ShortSK_before", str, 10, "Verdana", White); ObjectSet("ShortSK_before", OBJPROP_CORNER, 0); ObjectSet("ShortSK_before", OBJPROP_XDISTANCE, 20); ObjectSet("ShortSK_before", OBJPROP_YDISTANCE, height); height += 20; str = "ShortSD_before: " + DoubleToStr(ShortSD_before, 0); ObjectCreate("ShortSD_before", OBJ_LABEL, 0, 0, 0); ObjectSetText("ShortSD_before", str, 10, "Verdana", White); ObjectSet("ShortSD_before", OBJPROP_CORNER, 0); ObjectSet("ShortSD_before", OBJPROP_XDISTANCE, 20); ObjectSet("ShortSD_before", OBJPROP_YDISTANCE, height); } //+------------------------------------------------------------------+