//+------------------------------------------------------------------+ //| | //| Советник на разворот по | //| комбинации свечей | //| http://www.mql4.com/ru/users/ikatsko | //+------------------------------------------------------------------+ #property copyright "Ivan Katsko" #property link "ICQ:372739628" #include //---- extern double Lots = 0.1; // Жестко заданное колич. лотов ("0" - советник выбирает сам) extern double MaxRisk = 3; // Максимальный Loss в разах к свободным средствам extern int History = 125; // Колич.баров в расчётной истории extern int MaPerBegin = 4; extern int MaPerEnd = 22; extern int StDvErr = 5; //extern int AveragingPeriod = 3; extern int Variant = 1; // 1 рабоем в тренде, 2 работаем во флете, 0 работаем в обеих случаях extern int Wait = 1; // Задержка (в периодах) при изменении направления extern double MarginCutoff = 300; // Expert will stop trading if equity level decreases to that level. extern int Slippage = 4; // Possible fix for not getting closed Could be higher with some brokers //---- int MagicNumber; // Magic EA identifier. Allows for several co-existing EA with different input values int attempt = 5; //Попыток на открытие/закрытие ордеров string ExpertName; // To "easy read" which EA place an specific order and remember me forever :) string news_wav = "news.wav"; double lotMM, balans, old_balans, loss,price_buy, price_sell, time_buy, time_sell; double direction = 0, // Направление текущее : ">0" - купить; "<0" - продать old_direction = 0; // Направление предыдущее: ">0" - купить; "<0" - продать double stimul; double spread; bool Trand, Flat; bool MoneyManagement; // Change to false to shutdown money management controls. bool sound_yes = TRUE; //Разрешить звуки bool is_loss = false; static int prevtime = 0; //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { if (Time[0] == prevtime) { return(0); } prevtime = Time[0]; if(IsTradeAllowed()) { RefreshRates(); spread = (Ask - Bid) / Point; } else { again(); return(0); } int OpPzBUY = openPositionsBUY(false); // Открытых ордеров без отложенных int OpPzSELL = openPositionsSELL(false); int period = GetPeriod(History,MaPerBegin,MaPerEnd); old_direction = direction; //определяем настоящее направление direction = GetDirection(period); //определяем текущее направление if (old_direction != direction) { if (OpPzBUY > 0) if (price_buy+spread*Point < Open[0] || (Time[0]-time_buy)/60 >= Wait*Period()) CloseAllPos(OP_BUY); if (OpPzSELL > 0) if (price_sell-spread*Point > Open[0] || (Time[0]-time_sell)/60 >= Wait*Period()) CloseAllPos(OP_SELL); } else { if (direction > 0 && OpPzSELL > 0) if ((Time[0]-time_sell)/60 >= Wait*Period()) CloseAllPos(OP_SELL); if (direction < 0 && OpPzBUY > 0) if ((Time[0]-time_buy)/60 >= Wait*Period()) CloseAllPos(OP_BUY); return(0); } if (direction > 0 && OpPzBUY == 0) { if(AccountFreeMargin() < MarginCutoff) { Print("Not enough money for buy to trade Strategy:", ExpertName); return(0); } lotMM=GetLots(); OpenBuy(); } if (direction < 0 && OpPzSELL == 0) { if(AccountFreeMargin() < MarginCutoff) { Print("Not enough money for sell to trade Strategy:", ExpertName); return(0); } lotMM=GetLots(); OpenSell(); } return(0); } //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { if (Variant < 0) Variant = 0; if (Variant > 2) Variant = 2; switch (Variant) { case 0: Trand = true; Flat = true; break; case 1: Trand = true; Flat = false; break; case 2: Trand = false; Flat = true; break; } prevtime = Time[0]; old_balans = AccountBalance(); MagicNumber=3000 + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); ExpertName="iK_StDv: " + MagicNumber + " : " + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period())); return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| OpenBuy | //+------------------------------------------------------------------+ int OpenBuy() { int err, ticket; double myPrice = NormalizeDouble(Ask,Digits); if (Close[1] > Open[1]) double myStopLoss = NormalizeDouble(myPrice - ((Open[1]-Low[1])+0.23*(High[1]-Low[1])),Digits); else myStopLoss = NormalizeDouble(myPrice - ((Close[1]-Low[1])+0.23*(High[1]-Low[1])),Digits); ticket=OrderSend(Symbol(),OP_BUY,lotMM,myPrice,Slippage,0,0,ExpertName, MagicNumber); if(ticket<=0) { err=GetLastError(); return(0); } return(1); } //+------------------------------------------------------------------+ //| OpenSell | //+------------------------------------------------------------------+ int OpenSell() { int err, ticket; double myPrice = NormalizeDouble(Bid,Digits); if (Close[1] > Open[1]) double myStopLoss = NormalizeDouble(myPrice + ((High[1]-Close[1])+0.23*(High[1]-Low[1])),Digits); else myStopLoss = NormalizeDouble(myPrice + ((High[1]-Open[1])+0.23*(High[1]-Low[1])),Digits); ticket=OrderSend(Symbol(),OP_SELL,lotMM,myPrice,Slippage,0,0,ExpertName, MagicNumber); if(ticket<=0) { err=GetLastError(); return(0); } return(1); } //+------------------------------------------------------------------------+ //| counts the number of open positions BUY | //+------------------------------------------------------------------------+ int openPositionsBUY(bool limit = true) { int op =0; for(int i=OrdersTotal()-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if(OrderSymbol()==Symbol()) { if(OrderType()==OP_BUY) { op++; price_buy = OrderOpenPrice(); time_buy = OrderOpenTime(); } if(limit && OrderType()==OP_BUYLIMIT)op++; } } return(op); } //+------------------------------------------------------------------------+ //| counts the number of open positions SELL | //+------------------------------------------------------------------------+ int openPositionsSELL(bool limit = true) { int op =0; for(int i=OrdersTotal()-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if(OrderSymbol()==Symbol()) { if(OrderType()==OP_SELL) { op++; price_sell = OrderOpenPrice(); time_sell = OrderOpenTime(); } if(limit && OrderType()==OP_SELLLIMIT)op++; } } return(op); } //+------------------------------------------------------------------+ //| Get number of lots for this trade | //+------------------------------------------------------------------+ double GetLots() { double lot, Min_Lot=MarketInfo(Symbol(),MODE_MINLOT), // Миним. колич. лотов Max_Lot=MarketInfo(Symbol(),MODE_MAXLOT), // Миним. колич. лотов Free =AccountFreeMargin(), // Свободн средства One_Lot=MarketInfo(Symbol(),MODE_MARGINREQUIRED),// Стоимость 1 лота Step =MarketInfo(Symbol(),MODE_LOTSTEP); // Шаг изменен размера lot = Lots; loss = GetProfitLastClosePos(); if (loss < 0) lot=MaxRisk*lot; if (lot > Max_Lot) { lot = Max_Lot; Comment("ЛОТ ограничен максимумом и равен ",MathCeil(lot/Step)*Step); } if (lot*One_Lot > Free) { lot = Free/One_Lot; Comment("ЛОТ ограничен свободными средствами и равен ",MathCeil(lot/Step)*Step); } if (lot < Min_Lot) { lot=Min_Lot; // Не меньше минимальн Comment("ЛОТ ограничен минимумом и равен ",MathCeil(lot/Step)*Step); } RefreshRates(); // Обновление данных Step = MarketInfo(Symbol(),MODE_LOTSTEP); // Шаг изменен размера lot = MathCeil(lot/Step)*Step; return(lot); } //+------------------------------------------------------------------+ int GetProfitLastClosePos(string sy="", int mn=-1) { datetime t; int i, k=OrdersHistoryTotal(), r=0; if (sy=="0") sy=Symbol(); for (i=0; i= 0; l_pos_18--) { if (OrderSelect(l_pos_18, SELECT_BY_POS, MODE_TRADES)) { ClosePosBySelect(typ); l_ord_total_24--; } } if (l_ord_total_24 == 0) return; } void ClosePosBySelect(int typ) { bool l_ord_close_0; //color l_color_4; double l_ord_lots_8; double ld_16; double ld_24; double l_price_32; int l_error_40; if (OrderType() == OP_BUY || OrderType() == OP_SELL) { for (int li_44 = 1; li_44 <= attempt; li_44++) { if (!IsTesting() && !IsExpertEnabled() || IsStopped()) break; while (!IsTradeAllowed()) Sleep(5000); RefreshRates(); ld_16 = NormalizeDouble(MarketInfo(OrderSymbol(), MODE_ASK), Digits); ld_24 = NormalizeDouble(MarketInfo(OrderSymbol(), MODE_BID), Digits); if (OrderType() == OP_BUY) { l_price_32 = ld_24; } else { l_price_32 = ld_16; } l_ord_lots_8 = OrderLots(); if (typ == 2) l_ord_close_0 = OrderClose(OrderTicket(), l_ord_lots_8, l_price_32, Slippage); else if (typ == OrderType()) l_ord_close_0 = OrderClose(OrderTicket(), l_ord_lots_8, l_price_32, Slippage); if (l_ord_close_0) { if (!(sound_yes)) break; PlaySound(news_wav); return; } l_error_40 = GetLastError(); if (l_error_40 == 146/* TRADE_CONTEXT_BUSY */) while (IsTradeContextBusy()) Sleep(11000); Print("Error(", l_error_40, ") Close ", OrderType(), " ", ErrorDescription(l_error_40), ", try ", li_44); Sleep(5000); } } else Print("Некорректная торговая операция. Close ", OrderType()); } //+------------------------------------------------------------------+ void again() { prevtime = Time[1]; Sleep(30000); } //-------------------------------------------------------------------+ int GetPeriod(int History=140, int MaPerBegin=4, int MaPerEnd=24) { double max = 0.0; for (int period = MaPerBegin; period <= MaPerEnd; period++) { double ok_p = 0.01; double ok_m = 0.02; for (int i=History; i>=0; i--) { bool white_0 = false; bool black_0 = false; bool white_1 = false; bool black_1 = false; if (Close[i] >Open[i]) white_0 = true; if (Close[i] Open[i+1]) white_1 = true; if (Close[i+1] iStdDev(NULL,0,period,0,0,1,i+1)) flat = false; // } else { // if (iCustom(NULL,0,"_StdDev",period,AveragingPeriod,0,i) > iCustom(NULL,0,"_StdDev",period,AveragingPeriod,0,i+1)) flat = false; // } switch (Variant) { case 1: if (!flat) { if ((white_0 && white_1) || (black_0 && black_1)) { ok_p = ok_p + 1; } else { ok_m = ok_m + 1; } } break; case 2: if (flat) { if ((white_0 && black_1) || (black_0 && white_1)) { ok_p = ok_p + 1; } else { ok_m = ok_m + 1; } } break; default: if (((flat && ((white_0 && black_1) || (black_0 && white_1)))) || ((!flat && ((white_0 && white_1) || (black_0 && black_1))))) { ok_p = ok_p + 1; } else ok_m = ok_m + 1; break; } } if (ok_p/ok_m > max) { max = ok_p/ok_m; if (max > 1) int per = period; else per = 0; } } Comment("History=",History," period=",per," max=",max); return(per); } //------------------------------------------------------------------+ double GetDirection(int prd) { if (prd == 0) return(0); // if (AveragingPeriod == 0) { double sd0 = iStdDev(NULL,0,prd,0,0,1,0); double sd1 = iStdDev(NULL,0,prd,0,0,1,1); double stdv = sd0 - sd1; if (MathAbs(stdv) <= 0.01*StDvErr*sd0) stdv = 0; // } else // stdv = iCustom(NULL,0,"_StdDev",prd,AveragingPeriod,0,0) - iCustom(NULL,0,"_StdDev",prd,AveragingPeriod,0,1); switch (Variant) { case 1: if (stdv > 0) { if (iClose(0,0,1) > iOpen(0,0,1)) return(1); if (iClose(0,0,1) < iOpen(0,0,1)) return(-1); } else return(0); case 2: if (stdv < 0) { if (iClose(0,0,1) > iOpen(0,0,1)) return(-1); if (iClose(0,0,1) < iOpen(0,0,1)) return(1); } else return(0); default: if (stdv > 0) { if (iClose(0,0,1) > iOpen(0,0,1)) return(1); if (iClose(0,0,1) < iOpen(0,0,1)) return(-1); } if (stdv < 0) { if (iClose(0,0,1) > iOpen(0,0,1)) return(-1); if (iClose(0,0,1) < iOpen(0,0,1)) return(1); } if (stdv == 0) { return(0); } } }