//+------------------------------------------------------------------+ //| Stairs.mq4 | //| Copyright © 2008, Tinytjan | //| tinytjan@mail.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, Tinytjan" #property link "tinytjan@mail.ru" // magic number needed for filtering orders opened by certain EA extern int Magic = 12345; extern string TradeLots_ = "lots size of opening orders. If 0 it is counted automatically"; extern double TradeLots = 0; extern string RiskPercentage_ = "risk for automatic lots size counting"; extern double RiskPercentage = 0; extern string Slippage_ = "maximum acceptable slippage for the price"; extern int Slippage = 30; extern string TimesToRepeat_ = "maximum loop count for orders opening if failed due to requoting"; extern int TimesToRepeat = 3; extern string Channel_ = "Channel size in points"; extern int Channel = 50; extern string Profit_ = "Profit in points for all orders of the instrument enough to close"; extern int Profit = 290; extern string CommonProfit_ = "Profit in points for all orders of all instruments enough to close"; extern int CommonProfit = 700; extern string AddLots_ = "Use lots increasing"; extern int AddLots = 1; extern string MaxIncrease_ = "Max increase size = starting lot* MaxIncrease"; extern int MaxIncrease = 4; extern string StartSleep_ = "Starting sleeping hour"; extern int StartSleep = 18; extern string EndSleep_ = "Last sleeping hour"; extern int EndSleep = 6; extern string UseSleep_ = "Use sleeping during sleep hours(no new cycles starting)"; extern int UseSleep = 0; extern string CPUEconomy_ = "For trade -- if true Plase the EA to M1 chart. It will process 1 time a minute"; extern int CPUEconomy = 0; string symbol; double Lots; datetime LastTime; string CloseAll = "StairsCloseAll"; string StartLots = "StartLots"; /// \brief Equal to ternar operator /// needed = Condition ? IfTrue : IfFalse; /// \param IfTrue /// \param IfFalse /// \return matching value from parameters double DoubleIf(bool Condition, double IfTrue, double IfFalse) { if (Condition) return (IfTrue); else return (IfFalse); } void WaitForContext() { while (IsTradeContextBusy()) { Sleep(100); } } void OpenBuyStop(int MN, double Price, int Target, int Loss, double Lot) { double TP = DoubleIf(Target > 0, Price + Target*Point, 0); double SL = DoubleIf(Loss > 0, Price - Loss*Point, 0); double LotsToBid = DoubleIf(Lot == 0, GetLotsToBid(RiskPercentage), Lot); WaitForContext(); OrderSend(Symbol(), OP_BUYSTOP, LotsToBid, Price, Slippage, SL, TP, NULL, MN, 0, Blue); } void OpenSellStop(int MN, double Price, int Target, int Loss, double Lot) { Price = Price + Bid - Ask; double TP = DoubleIf(Target > 0, Price - Target*Point, 0); double SL = DoubleIf(Loss > 0, Price + Loss*Point, 0); double LotsToBid = DoubleIf(Lot == 0, GetLotsToBid(RiskPercentage), Lot); WaitForContext(); OrderSend(Symbol(), OP_SELLSTOP, LotsToBid, Price, Slippage, SL, TP, NULL, MN, 0, Red); } void CloseSells(int MagicNumber, int Slippage) { for(int i = OrdersTotal() - 1; i >= 0; i--) { // already closed if(OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if(OrderSymbol() != Symbol()) continue; // order was opened in another way if(OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_SELL) { int count = 0; while (count < TimesToRepeat) { WaitForContext(); RefreshRates(); if (OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, Red)) { break; } count++; } } } } void CloseBuys(int MagicNumber, int Slippage) { for(int i = OrdersTotal(); i >= 0; i--) { // already closed if(OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if(OrderSymbol() != Symbol()) continue; // order was opened in another way if(OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY) { int count = 0; while (count < TimesToRepeat) { WaitForContext(); RefreshRates(); if (OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Blue)) { break; } count++; } } } } void DeletePending(int MagicNumber = -1) { for(int i = OrdersTotal() - 1; i >= 0; i--) { // already closed if(OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if(OrderSymbol() != Symbol()) continue; // order was opened in another way if(OrderMagicNumber() != MagicNumber && MagicNumber != -1) continue; if(OrderType() != OP_SELL && OrderType() != OP_BUY) { WaitForContext(); OrderDelete(OrderTicket()); } } } bool GetActiveOrders(int MagicNumber = -1) { for(int i = 0; i < OrdersTotal(); i++) { // already closed if(OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if(OrderSymbol() != Symbol()) continue; // order was opened in another way if(OrderMagicNumber() != MagicNumber && MagicNumber != -1) continue; if(OrderType() == OP_SELL || OrderType() == OP_BUY) { return (true); } } return (false); } int GetOrdersCount(int MagicNumber = -1, int Type = -1, string symb = "") { int count = 0; for(int i = 0; i < OrdersTotal(); i++) { // already closed if(OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if(OrderSymbol() != Symbol() && symb == "") continue; // not specified symbol if(OrderSymbol() != symb && symb != "" && symb != "all") continue; // order was opened in another way if(OrderMagicNumber() != MagicNumber && MagicNumber != -1) continue; if(OrderType() == Type || Type == -1) { count++; } } return (count); } double GetLotsToBid(double RiskPercentage) { double margin = MarketInfo(Symbol(), MODE_MARGINREQUIRED); double minLot = MarketInfo(Symbol(), MODE_MINLOT); double maxLot = MarketInfo(Symbol(), MODE_MAXLOT); double step = MarketInfo(Symbol(), MODE_LOTSTEP); double account = AccountFreeMargin(); double percentage = account*RiskPercentage/100; double lots = MathRound(percentage/margin/step)*step; if(lots < minLot) { lots = minLot; } if(lots > maxLot) { lots = maxLot; } return (lots); } bool IsSleepTime() { if (UseSleep == 0) return (false); int hour = TimeHour(TimeCurrent()); return (hour > StartSleep || hour < EndSleep); } bool IsStart() { double buyStopPrice = 0; double sellStopPrice = 0; for(int i = 0; i < OrdersTotal(); i++) { // already closed if(OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if(OrderSymbol() != Symbol()) continue; // order was opened in another way if(OrderMagicNumber() != Magic) continue; if(OrderType() == OP_SELLSTOP) { sellStopPrice = OrderOpenPrice(); } if(OrderType() == OP_BUYSTOP) { buyStopPrice = OrderOpenPrice(); } } if (buyStopPrice == 0 || sellStopPrice == 0) { return (false); } double distance = (buyStopPrice - sellStopPrice)/Point; return (distance < 1.5*Channel && distance > 0.5*Channel); } int GetLastOpenedTicket(int MN) { datetime lastTime = 0; int lastTicket = -1; for(int i = 0; i < OrdersTotal(); i++) { // already closed if(OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if(OrderSymbol() != Symbol()) continue; // order was opened in another way if(OrderMagicNumber() != MN) continue; if (OrderOpenTime() > lastTime) { lastTime = OrderOpenTime(); lastTicket = OrderTicket(); } } return (lastTicket); } double GetLastLot(int MN) { int ticket = GetLastOpenedTicket(MN); if (OrderSelect(ticket, SELECT_BY_TICKET)) { return (OrderLots()); } double lots = TradeLots; if (TradeLots == 0) { lots = GetLotsToBid(RiskPercentage); } return (lots); } double GetLastPrice(int MN) { int ticket = GetLastOpenedTicket(MN); if (OrderSelect(ticket, SELECT_BY_TICKET)) { return (OrderOpenPrice()); } return(0); } void Check() { string name = Symbol() + StartLots; if (!GlobalVariableCheck(CloseAll)) { GlobalVariableSet(CloseAll, EMPTY_VALUE); } else { double value = GlobalVariableGet(CloseAll); if (value == 1) { if (GetOrdersCount(Magic) > 0) { CloseSells(Magic, Slippage); CloseBuys(Magic, Slippage); DeletePending(Magic); } RefreshRates(); if (GetOrdersCount(Magic, -1, "all") == 0) { GlobalVariableSet(CloseAll, EMPTY_VALUE); } else { return; } } } int SL = Channel + MathRound((Ask - Bid)/Point); if (GetOrdersCount(Magic) == 0) { if (IsSleepTime()) return(0); double lot = DoubleIf(TradeLots == 0, GetLotsToBid(RiskPercentage), TradeLots); GlobalVariableSet(name, lot); int distanse = Channel/2; OpenBuyStop(Magic, Ask + distanse*Point, 0, SL, lot); OpenSellStop(Magic, Ask - distanse*Point, 0, SL, lot); } if (!GetActiveOrders(Magic)) { if (GetOrdersCount(Magic) > 0) { if (!IsStart()) { // îñòàëèñü îòëîæêè // ýòî ñîñòîÿíèå êîíå÷íîå // óäàëÿåì DeletePending(Magic); } } return; } if (GetOrdersCount(Magic, OP_BUYSTOP) + GetOrdersCount(Magic, OP_SELLSTOP) < 2 && GetActiveOrders(Magic)) { // îòëîæêà ñðàáîòàëà, íàäî âûñòàâèòü çàíîâî // èëè ïîñòíà÷àëüíîå ñîñòîÿíèå, íàäî ðàññòàâèòü ñåòü. DeletePending(Magic); double lastOpenPrice = GetLastPrice(Magic); double lastOpenLots = GetLastLot(Magic); double addLot = GlobalVariableGet(name); if (AddLots == 1) { lastOpenLots += addLot; if (lastOpenLots > addLot*MaxIncrease) { lastOpenLots = addLot*MaxIncrease; } } OpenBuyStop(Magic, lastOpenPrice + Channel*Point, 0, SL, lastOpenLots); OpenSellStop(Magic, lastOpenPrice - Channel*Point, 0, SL, lastOpenLots); } double profit = 0; for(int i = 0; i < OrdersTotal(); i++) { // already closed if (OrderSelect(i, SELECT_BY_POS) == false) continue; // not current symbol if (OrderSymbol() != symbol) continue; // order was opened in another way if (OrderMagicNumber() != Magic) continue; int type = OrderType(); if (type != OP_SELL && type != OP_BUY) continue; double add = DoubleIf(type == OP_BUY, Bid - OrderOpenPrice(), OrderOpenPrice() - Ask); profit += add/Point; } if (profit > Profit) { CloseSells(Magic, Slippage); CloseBuys(Magic, Slippage); } profit = 0; for(i = 0; i < OrdersTotal(); i++) { // already closed if (OrderSelect(i, SELECT_BY_POS) == false) continue; // order was opened in another way if (OrderMagicNumber() != Magic) continue; type = OrderType(); if (type != OP_SELL && type != OP_BUY) continue; add = OrderOpenPrice() - MarketInfo(OrderSymbol(), MODE_ASK); if (type == OP_BUY) add = MarketInfo(OrderSymbol(), MODE_BID) - OrderOpenPrice(); profit += add/MarketInfo(OrderSymbol(), MODE_POINT); } if (profit > CommonProfit) { GlobalVariableSet(CloseAll, 1); } } int init() { Lots = TradeLots; symbol = Symbol(); LastTime = Time[0]; } int start() { if (CPUEconomy == 1 && LastTime == Time[0]) return(0); LastTime = Time[0]; if (!IsTradeAllowed()) return(0); Check(); return(0); }
Sample
Analysis
Market Information Used:
Series array that contains open time of each bar
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
Order Management characteristics:
It automatically opens orders when conditions are reached
Checks for the total of open orders
It Closes Orders by itself
Other Features: