- www.mql5.com
- Элементарная задачка для начинающих программистов)
- Отвечу на вопросы по программированию в MQL4
- Вопросы от начинающих MQL4 MT4 MetaTrader 4
//+------------------------------------------------------------------+ //| TrailingP.mq5 | //| Copyright 2020, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2020, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #define MACD_MAGIC 0 //--- #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> #include <Trade\PositionInfo.mqh> #include <Trade\AccountInfo.mqh> #include <Trade\OrderInfo.mqh> #include <Trade\DealInfo.mqh> //--- CTrade m_trade; // trading object CSymbolInfo m_symbol; // symbol info object CPositionInfo m_position; // trade position object CAccountInfo m_account; // account info wrapper COrderInfo m_order; // pending orders object CDealInfo m_deal; // deals object input double InpLots = 0.01; // Lots input string t2="------ Trailing parameters ------";// input ushort InpTrailingStop = 25; // Trailing Stop (min distance from price to Stop Loss, in pips input ushort InpTrailingStep = 5; // Trailing Step, in pips (1.00045-1.00055=1 pips) sinput string t1="------ Как работать Grid---"; // input bool InpPanel = false; // Скрыть кнопки input ushort TakeProfit = 2000; // Take profit input ushort Grid_step = 250; // Grid step input ushort N_orders = 1; // Number of orders in one direction input ushort Distance = 150; // Price offset input string t4="------ Trailing ордеров ------"; // input bool InpStopTrailing = true; // ВКЛ.Trailing отлож.ордеров(ВЫКЛ.если больше 1 в сетке) input ushort InpTrailingPenStop = 25; // Trailing Stop of a Orders. "0" --> off and Trailing Step is not important input ushort InpTrailingPenStep = 5; // Trailing Step of a Orders //+------------------------------------------------------------------+ bool WaitProfit= true; // Wait profit, "true" -> wait breakeven double InpStopLoss= 0.0; // Stop Loss int InpTakeProfit= 0.0; // Take Profit double NewPrice,SL,TP; int SchBuyStop,SchSellStop,SchBuyLimit,SchSellLimit,SchSell,SchBuy; long MinLevel; double m_take_TrailingStop= 0; double m_take_TrailingStep= 0; double m_take_TrailingPenStop= 0; double m_take_TrailingPenStep= 0; double m_adjusted_point; // point value adjusted for 3 or 5 points //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- if(IsFillingTypeAllowed(SYMBOL_FILLING_FOK)) m_trade.SetTypeFilling(ORDER_FILLING_FOK); else if(IsFillingTypeAllowed(SYMBOL_FILLING_IOC)) m_trade.SetTypeFilling(ORDER_FILLING_IOC); else m_trade.SetTypeFilling(ORDER_FILLING_RETURN); //--- if(!IsTradeAllowed()) return(true); //--- initialize common information MinLevel=m_symbol.StopsLevel(); m_symbol.Name(Symbol()); // symbol m_trade.SetExpertMagicNumber(MACD_MAGIC); // magic m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(Symbol()); m_trade.SetDeviationInPoints(10); //--- tuning for 3 or 5 digits int digits_adjust=1; if(m_symbol.Digits()==3 || m_symbol.Digits()==5) digits_adjust=10; m_adjusted_point=m_symbol.Point()*digits_adjust; //--- set default deviation for trading in adjusted points m_take_TrailingStop = InpTrailingStop*m_adjusted_point; m_take_TrailingStep = InpTrailingStep*m_adjusted_point; m_take_TrailingPenStop = InpTrailingPenStop*m_adjusted_point; m_take_TrailingPenStep = InpTrailingPenStep*m_adjusted_point; //--- set default deviation for trading in adjusted points m_trade.SetDeviationInPoints(3*digits_adjust); //--- bool res=false; if(!InpPanel) { ObjectCreate(0,"BUY",OBJ_BUTTON,0,0,0); ObjectSetInteger(0,"BUY",OBJPROP_XDISTANCE,ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-102); ObjectSetInteger(0,"BUY",OBJPROP_YDISTANCE,37); ObjectSetString(0,"BUY",OBJPROP_TEXT,"BUY"); ObjectSetInteger(0,"BUY",OBJPROP_BGCOLOR,clrMediumSeaGreen); ObjectCreate(0,"SELL",OBJ_BUTTON,0,0,0); ObjectSetInteger(0,"SELL",OBJPROP_XDISTANCE,ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-50); ObjectSetInteger(0,"SELL",OBJPROP_YDISTANCE,37); ObjectSetString(0,"SELL",OBJPROP_TEXT,"SELL"); ObjectSetInteger(0,"SELL",OBJPROP_BGCOLOR,clrDarkOrange); } res=true; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- ObjectsDeleteAll(0,"BUY"); ObjectsDeleteAll(0,"SELL"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick(void) { //--- if(!m_symbol.RefreshRates()) return; Trailing(); //--- if(ObjectGetInteger(0,"BUY",OBJPROP_STATE)!=0) { ObjectSetInteger(0,"BUY",OBJPROP_STATE,0); OnStartLimit(); return; } if(ObjectGetInteger(0,"SELL",OBJPROP_STATE)!=0) { ObjectSetInteger(0,"SELL",OBJPROP_STATE,0); OnStartStop(); return; } } //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| Trailing | //| InpTrailingStop: min distance from price to Stop Loss | //+------------------------------------------------------------------+ bool Trailing(void) { //--- Primary Data Validation if(!IsTradeAllowed()) return(true); //--- Trailing positions SchOrders(); if(SchBuy>0 || SchSell>0) { if(InpTrailingStop>=MinLevel && InpTrailingStep>0) { for(int i=PositionsTotal()-1; i>=0; i--) if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==MACD_MAGIC) { if(m_position.PositionType()==POSITION_TYPE_BUY) { if(!WaitProfit || (m_position.PriceCurrent()-m_position.PriceOpen())>InpTrailingStop*m_adjusted_point) { if(m_position.StopLoss()<m_position.PriceCurrent()-(InpTrailingStop+InpTrailingStep-1)*m_adjusted_point) { if(!m_trade.PositionModify(m_position.Ticket(), m_symbol.NormalizePrice(m_position.PriceCurrent()-InpTrailingStop*m_adjusted_point), m_position.TakeProfit())) Print("Modify BUY ",m_position.Ticket(), " Position -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); continue; } } } if(m_position.PositionType()==POSITION_TYPE_SELL) { if(!WaitProfit || m_position.PriceOpen()-m_position.PriceCurrent()>InpTrailingStop*m_adjusted_point) { if(m_position.StopLoss()>m_position.PriceCurrent()+(InpTrailingStop+InpTrailingStep-1)*m_adjusted_point || m_position.StopLoss()==0.0) { if(!m_trade.PositionModify(m_position.Ticket(), m_symbol.NormalizePrice(m_position.PriceCurrent()+InpTrailingStop*m_adjusted_point), m_position.TakeProfit())) Print("Modify SELL ",m_position.Ticket(), " Position -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of result: ",m_trade.ResultRetcodeDescription()); continue; } } } } } else if(InpTrailingStop>=MinLevel && InpTrailingStep==0) { Print("ERROR: \"Trailing Step of positions\" can not be 0"); Comment("ERROR: \"Trailing Step of positions\" can not be 0"); } } SchOrders(); if(InpStopTrailing) if((InpTrailingPenStop>0 && SchBuyStop+SchSellStop>0) || (SchBuyLimit+SchSellLimit>0 && InpTrailingPenStop>0)) { //--- for(int i=OrdersTotal()-1; i>=0; i--) // returns the number of current orders if(m_order.SelectByIndex(i)) // selects the pending order by index for further access to its properties if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==MACD_MAGIC) { if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT) // He's downstairs and goes up if(m_order.PriceCurrent()>m_order.PriceOpen()+(InpTrailingPenStop+InpTrailingPenStep)*m_adjusted_point) { NewPrice=m_order.PriceCurrent()-InpTrailingPenStop*m_adjusted_point; if(InpStopLoss==0) SL=0.0; else SL=NewPrice-InpStopLoss*m_adjusted_point; if(InpTakeProfit==0) TP=0.0; else TP=NewPrice+InpTakeProfit*m_adjusted_point; if(m_trade.OrderModify(m_order.Ticket(), m_symbol.NormalizePrice(NewPrice), m_symbol.NormalizePrice(SL), m_symbol.NormalizePrice(TP), m_order.TypeTime(), m_order.TimeExpiration())) Print("Modify BUY LIMIT - > true. ticket of order = ",m_trade.ResultOrder()); else Print("Modify BUY LIMIT -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of Retcode: ",m_trade.ResultRetcodeDescription()); } if(m_order.OrderType()==ORDER_TYPE_SELL_LIMIT) // He's upstairs and is driving down if(m_order.PriceCurrent()<m_order.PriceOpen()-(InpTrailingPenStop+InpTrailingPenStep)*m_adjusted_point) { NewPrice=m_order.PriceCurrent()+InpTrailingPenStop*m_adjusted_point; if(InpStopLoss==0) SL=0.0; else SL=NewPrice+InpStopLoss*m_adjusted_point; if(InpTakeProfit==0) TP=0.0; else TP=NewPrice-InpTakeProfit*m_adjusted_point; if(m_trade.OrderModify(m_order.Ticket(), m_symbol.NormalizePrice(NewPrice), m_symbol.NormalizePrice(SL), m_symbol.NormalizePrice(TP), m_order.TypeTime(), m_order.TimeExpiration())) Print("Modify SELL LIMIT - > true. ticket of order = ",m_trade.ResultOrder()); else Print("Modify SELL LIMIT -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of Retcode: ",m_trade.ResultRetcodeDescription()); } if(m_order.OrderType()==ORDER_TYPE_BUY_STOP) // He's upstairs and is driving down if(m_order.PriceCurrent()<m_order.PriceOpen()-(InpTrailingPenStop+InpTrailingPenStep)*m_adjusted_point) { NewPrice=m_order.PriceCurrent()+InpTrailingPenStop*m_adjusted_point; if(InpStopLoss==0) SL=0.0; else SL=NewPrice-InpStopLoss*m_adjusted_point; if(InpTakeProfit==0) TP=0.0; else TP=NewPrice+InpTakeProfit*m_adjusted_point; if(m_trade.OrderModify(m_order.Ticket(), m_symbol.NormalizePrice(NewPrice), m_symbol.NormalizePrice(SL), m_symbol.NormalizePrice(TP), m_order.TypeTime(), m_order.TimeExpiration())) Print("Modify BUY STOP - > true. ticket of order = ",m_trade.ResultOrder()); else Print("Modify BUY STOP -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of Retcode: ",m_trade.ResultRetcodeDescription()); } if(m_order.OrderType()==ORDER_TYPE_SELL_STOP) // He's downstairs and goes up !!!! if(m_order.PriceCurrent()>m_order.PriceOpen()+(InpTrailingPenStop+InpTrailingPenStep)*m_adjusted_point) { NewPrice=m_order.PriceCurrent()-InpTrailingPenStop*m_adjusted_point; if(InpStopLoss==0) SL=0.0; else SL=NewPrice+InpStopLoss*m_adjusted_point; if(InpTakeProfit==0) TP=0.0; else TP=NewPrice-InpTakeProfit*m_adjusted_point; if(m_trade.OrderModify(m_order.Ticket(), m_symbol.NormalizePrice(NewPrice), m_symbol.NormalizePrice(SL), m_symbol.NormalizePrice(TP), m_order.TypeTime(), m_order.TimeExpiration())) Print("Modify SELL STOP - > true. ticket of order = ",m_trade.ResultOrder()); else Print("Modify SELL STOP -> false. Result Retcode: ",m_trade.ResultRetcode(), ", description of Retcode: ",m_trade.ResultRetcodeDescription()); } } } //--- return(true); } //+------------------------------------------------------------------+ //| SchOrders | //+------------------------------------------------------------------+ void SchOrders(void) { //--- Before starting work, we reset the counters SchBuy=0; SchSell=0; SchBuyLimit=0; SchSellLimit=0; SchBuyStop=0; SchSellStop=0; for(int i=PositionsTotal()-1; i>=0; i--) if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties if(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==MACD_MAGIC) { if(m_position.PositionType()==POSITION_TYPE_BUY) SchBuy++; if(m_position.PositionType()==POSITION_TYPE_SELL) SchSell++; } for(int i=OrdersTotal()-1; i>=0; i--) // returns the number of current orders if(m_order.SelectByIndex(i)) // selects the pending order by index for further access to its properties if(m_order.Symbol()==m_symbol.Name() && m_order.Magic()==MACD_MAGIC) { if(m_order.OrderType()==ORDER_TYPE_BUY_LIMIT) SchBuyLimit++; if(m_order.OrderType()==ORDER_TYPE_SELL_LIMIT) SchSellLimit++; if(m_order.OrderType()==ORDER_TYPE_BUY_STOP) SchBuyStop++; if(m_order.OrderType()==ORDER_TYPE_SELL_STOP) SchSellStop++; } } //+------------------------------------------------------------------+ //| Refreshes the symbol quotes data | //+------------------------------------------------------------------+ bool RefreshRates(void) { //--- refresh rates if(!m_symbol.RefreshRates()) { Print("RefreshRates error"); return(false); } //--- protection against the return value of "zero" if(m_symbol.Ask()==0 || m_symbol.Bid()==0) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| Checks if the specified filling mode is allowed | //+------------------------------------------------------------------+ bool IsFillingTypeAllowed(int fill_type) { //--- Obtain the value of the property that describes allowed filling modes int filling=m_symbol.TradeFillFlags(); //--- Return true, if mode fill_type is allowed return((filling & fill_type)==fill_type); } //+------------------------------------------------------------------+ //| Gets the information about permission to trade | //+------------------------------------------------------------------+ bool IsTradeAllowed(void) { if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Alert(__FUNCTION__,", ERROR: Check if automated trading is allowed in the terminal settings!"); return(false); } else { if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) { Alert(__FUNCTION__,", ERROR: Automated trading is forbidden in the program settings for ",__FILE__); return(false); } } if(!AccountInfoInteger(ACCOUNT_TRADE_EXPERT)) { Alert(__FUNCTION__,", ERROR: Automated trading is forbidden for the account ",AccountInfoInteger(ACCOUNT_LOGIN), " at the trade server side"); return(false); } if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED)) { Comment(__FUNCTION__,", ERROR: Trading is forbidden for the account ",AccountInfoInteger(ACCOUNT_LOGIN), ".\n Perhaps an investor password has been used to connect to the trading account.", "\n Check the terminal journal for the following entry:", "\n\'",AccountInfoInteger(ACCOUNT_LOGIN),"\': trading has been disabled - investor mode."); return(false); } //--- return(true); } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStartStop() { //--- for(int j=1; j<=N_orders; j++) { double _pricebuy = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK)+Distance*_Point+Grid_step*j*_Point,_Digits); double _pricesell = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID)-Distance*_Point-Grid_step*j*_Point,_Digits); m_trade.BuyStop(InpLots,_pricebuy,NULL,0,_pricebuy+TakeProfit*_Point,0,0,NULL); m_trade.SellStop(InpLots,_pricesell,NULL,0,_pricesell-TakeProfit*_Point,0,0,NULL); } } //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStartLimit() { //--- for(int j=1; j<=N_orders; j++) { double _pricebuy = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK)-Distance*_Point-Grid_step*j*_Point,_Digits); double _pricesell = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID)+Distance*_Point+Grid_step*j*_Point,_Digits); m_trade.SellLimit(InpLots,_pricesell,NULL,0,_pricesell-TakeProfit*_Point,0,0,NULL); m_trade.BuyLimit(InpLots,_pricebuy,NULL,0,_pricebuy+TakeProfit*_Point,0,0,NULL); } } //+------------------------------------------------------------------+
Функция - Трала, автор Vladimir Karputov - barabashkakvn - Профиль трейдера - MQL5.community
- из какого эксперта не помню.
Функция - Отложенных ордеров, автор Aleksandr Zakhvatkin - z.a.m - Профиль трейдера - MQL5.community
- оригинал здесь https://www.mql5.com/ru/code/30709
Очень красивый код!!! Радует глаз.
Но есть нестыковки.
Кнопки панели называются "BUY" и "SELL" , а должны называться "Limit" и "Stop", так как открывают соответственно лимитные и стоп ордера.
Магик обычно находится в настройках, а не в #define, согласитесь менять его в коде как то не айс, хотя и не сложно.
Артефакты остались от чего то: bool res = false; и чуть ниже res = true;
Ну и самое главное, чел спрашивал не про код трейлинга(хоть он у вас действительно хорош), а про то как сделать, чтоб трал срабатывал только один раз.
- www.metatrader5.com
Очень красивый код!!! Радует глаз.
Но есть нестыковки.
Кнопки панели называются "BUY" и "SELL" , а должны называться "Limit" и "Stop", так как открывают соответственно лимитные и стоп ордера.
Магик обычно находится в настройках, а не в #define, согласитесь менять его в коде как то не айс, хотя и не сложно.
Артефакты остались от чего то: bool res = false; и чуть ниже res = true;
Ну и самое главное, чел спрашивал не про код трейлинга(хоть он у вас действительно хорош), а про то как сделать, чтоб трал срабатывал только один раз.
это не готовое решение - это черновик так сказать, что бы можно было проверить, функции в тестере.
это не готовое решение - это черновик так сказать, что бы можно было проверить, функции в тестере.
Понятно.
Пока писал свой коммент, вы добавили пояснения к коду, что код писали разные люди. Это заметно.
Рекомендую в функциях выставляющих отложенные ордера заменить NormalizeDouble() на m_symbol.NormalizePrice() , на некоторых рынках это бывает полезно.
Понятно.
Пока писал свой коммент, вы добавили пояснения к коду, что код писали разные люди. Это заметно.
Рекомендую в функциях выставляющих отложенные ордера заменить NormalizeDouble() на m_symbol.NormalizePrice() , на некоторых рынках это бывает полезно.
ДА, когда тик например 0,025 NormalizeDouble не поможет
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования