Проблема не в значениях Bid и Ask. Скорее всего, дело в значениях переменных tradeResult, LastPrice и tradePrice. Из приведенного кода не понятно, как организуется преемственность значений этих переменных от одного тика к другому.
Кроме того, как-то странно происходит закрытие:
int i=PositionsTotal()-1; while(i>=0) { if(trade.PositionClose(_Symbol)) i--; } tradeResult=0;
То есть перебираются все позиции, но, вне зависимости от того, по какому они символу, закрывается позиция по текущему символу. Потом, не проверяя успешность закрытия позиции, происходит сброс флага tradeResult. Значит, если с первого раза закрыть позицию не удалось, то больше попыток произведено не будет.
P. S. Зачем нужно дублирование условий?
tradePrice<=bid || tradePrice<bid
Ведь первое условие включает в себя второе. То же самое с Ask.
Проблема не в значениях Bid и Ask. Скорее всего, дело в значениях переменных tradeResult, LastPrice и tradePrice. Из приведенного кода не понятно, как организуется преемственность значений этих переменных от одного тика к другому.
P. S. Зачем нужно дублирование условий?
Ведь первое условие включает в себя второе. То же самое с Ask.
Это весь код который выполняется в void OnTick().
Повторение условия нужно для того чтобы к последней цене подошла текущая цена и робот закрылся бы в плюсе. А второе условие нужно для того чтобы Робот закрылся в плюсе в любом другом случае - обычно это происходит через один тик.
По моему условия разные так как с начало выполняется условие в больших скобках.
Прошу прощения не тот ког.
Вот тот:
//+------------------------------------------------------------------+ //| LastPrice.mq5 | //| Copyright 2015, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" input int interval=100; //Мин. отклонение цены сделки input double Lots=1; //Лот input int SlPips=100; //Stop Loss input ENUM_ORDER_TYPE_FILLING Filling=ORDER_FILLING_RETURN; //Режим заполнения ордера #include <trade/trade.mqh> int tradeResult=0; double tradePrice=0,LastPrice=0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- ///GetPrice MqlTick last_tick; SymbolInfoTick(Symbol(),last_tick); double ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); /// ///BUY if(tradeResult==0) if(last_tick.last>=ask+interval) { MqlTradeRequest request={0}; MqlTradeResult result={0}; double spread = MathAbs(ask-bid); request.action=TRADE_ACTION_PENDING; // setting a pending order request.magic=68975; // ORDER_MAGIC request.symbol=_Symbol; // symbol request.volume=Lots; // volume in 0.1 lots request.sl=ask-SlPips; // Stop Loss is not specified //request.tp=NormalizeDouble(ask + TpPips * gTickSize, _Digits); // Take Profit is not specified request.type=ORDER_TYPE_BUY_LIMIT; // order type request.price=ask; // open price request.type_filling=Filling; request.deviation=0; request.type_time=ORDER_TIME_DAY; request.expiration=0; //--- send a trade request int i=PositionsTotal();//Wait openedPosition if(OrderSend(request,result)) { while(i==PositionsTotal())//Wait openedPosition { } tradeResult=1; tradePrice=ask; LastPrice=last_tick.last; } } /// ///SELL if(tradeResult==0) if(last_tick.last<=bid-interval) { MqlTradeRequest request={0}; MqlTradeResult result={0}; request.action=TRADE_ACTION_PENDING; // setting a pending order request.magic=68975; // ORDER_MAGIC request.symbol=_Symbol; // symbol request.volume=Lots; // volume in 0.1 lots request.sl=bid+SlPips; // Stop Loss is not specified //request.tp=NormalizeDouble(bid - TpPips * gTickSize, _Digits); // Take Profit is not specified request.type=ORDER_TYPE_SELL_LIMIT; // order type request.price=bid; // open price request.type_filling=Filling; request.deviation=0; request.type_time=ORDER_TIME_DAY; request.expiration=0; //--- send a trade request int i=PositionsTotal();//Wait openedPosition if(OrderSend(request,result)) { while(i==PositionsTotal())//Wait openedPosition { } tradeResult=2; tradePrice=bid; LastPrice=last_tick.last; } } ///ClosePosition if(tradeResult==2) ///if SELL position if(((LastPrice>=ask || LastPrice>=bid) && (tradePrice>=ask)) || (tradePrice>ask)) { CTrade trade; trade.SetTypeFilling(Filling); int i=PositionsTotal()-1; while(i>=0) { if(trade.PositionClose(_Symbol)) i--; } tradeResult=0; } if(tradeResult==1) ///if BUY position if(((LastPrice<=bid || LastPrice<=ask) && (tradePrice<=bid)) || (tradePrice<bid)) { CTrade trade; trade.SetTypeFilling(Filling); int i=PositionsTotal()-1; while(i>=0) { if(trade.PositionClose(_Symbol)) i--; } tradeResult=0; } /// ///PositionSL if(tradeResult!=0) if(!PositionSelect(_Symbol)) tradeResult=0; /// } //+------------------------------------------------------------------+
Это весь код который выполняется в void OnTick().
Повторение условия нужно для того чтобы к последней цене подошла текущая цена и робот закрылся бы в плюсе. А второе условие нужно для того чтобы Робот закрылся в плюсе в любом другом случае - обычно это происходит через один тик.
По моему условия разные так как с начало выполняется условие в больших скобках.
Прошу прощения не тот ког.
Вот тот:
Суть не меняется. В коде нет обработки случаев, когда закрытие позиции закончилось неудачно. Но несмотря на это, советник продолжает оперировать значением tradeResult = 0, т. е. считает, что позиции уже нет.
Вместо tradeResult лучше использовать проверку типа существующей позиции. А уже потом, определив тип, пытаться закрывать. Кроме того, нужно учесть, что метод trade.PositionClose всего лишь отсылает торговый приказ. Нужно еще дождаться результатов его выполнения, а то будете бомбить сервер приказами на закрытие между отправкой приказа и приходом результата.
Зачем Вы ещё раз берёте
double ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits); double bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
Если в структуре MqlTick уже есть эти данные?
struct MqlTick { datetime time; // Время последнего обновления цен double bid; // Текущая цена Bid double ask; // Текущая цена Ask double last; // Текущая цена последней сделки (Last) ulong volume; // Объем для текущей цены Last };
А это
if(last_tick.last>=ask+interval)
Ни "в какие ворота"!
last - double, ask -double, а interval - int !!!
Не используйте для ФОРТС стандартную библиотеку.
И на ФОРТС лучше использовать стаканы, нежели OnTick()
Вот "рыба":
//+------------------------------------------------------------------+ //| LastPrice.mq5 | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" // //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { if ( !MarketBookAdd( _Symbol ) ) { MessageBox( "Не добавлен стакан по символу " + _Symbol ); return( INIT_FAILED ); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { MarketBookRelease( _Symbol ); } //+------------------------------------------------------------------+ //| Get Stakan values function | //+------------------------------------------------------------------+ bool GetStakanValues( const string aSymbol, double &ask, double &bid ) { MqlBookInfo book_price[]; bid = 0; ask = DBL_MAX; //--- Get stakan if ( MarketBookGet( aSymbol, book_price ) ) { int size = ArraySize( book_price ); //--- if ( size > 0 ) { for( int i = 0; i < size; i++ ) { if ( book_price[i].type == BOOK_TYPE_SELL ) { if ( book_price[i].price < ask ) { ask = book_price[i].price; } } else if ( book_price[i].type == BOOK_TYPE_BUY ) { bid = book_price[i].price; return( true ); } } } } //--- if ( ask == DBL_MAX ) ask = 0; return( false); } //+------------------------------------------------------------------+ //| BookEvent function | //+------------------------------------------------------------------+ void OnBookEvent(const string &symbol) { if ( symbol == _Symbol ) { if ( PositionSelect( _Symbol ) ) { //--- } else { double ask, bid; //--- if ( GetStakanValues( _Symbol, ask, bid ) ) { //--- } } } } //+------------------------------------------------------------------+
Зачем Вы ещё раз берёте
Если в структуре MqlTick уже есть эти данные?
А это
Ни "в какие ворота"!
last - double, ask -double, а interval - int !!!
Не используйте для ФОРТС стандартную библиотеку.
И на ФОРТС лучше использовать стаканы, нежели OnTick()
Вот "рыба":
Я подумал что АСК и БИД таким образом возьмутся правильно, т.е. все значения которые идут на графике.
Спасибо за бук попробую разобраться.
Да кстати в другом брокере вроде позу сразу закрывает.
Суть не меняется. В коде нет обработки случаев, когда закрытие позиции закончилось неудачно. Но несмотря на это, советник продолжает оперировать значением tradeResult = 0, т. е. считает, что позиции уже нет.
Вместо tradeResult лучше использовать проверку типа существующей позиции. А уже потом, определив тип, пытаться закрывать. Кроме того, нужно учесть, что метод trade.PositionClose всего лишь отсылает торговый приказ. Нужно еще дождаться результатов его выполнения, а то будете бомбить сервер приказами на закрытие между отправкой приказа и приходом результата.
Так вроде есть цикл где проверяется условие на закрытие позиции - про который Вы ранее говорили.
Я кроме PositionSelect и копаться в истории сделок никаких проверок не знаю. Как то крутил PositionSelect в цикле и через пол дня он дал сбой. Может есть альтернатива попроще хистори?
Так вроде есть цикл где проверяется условие на закрытие позиции - про который Вы ранее говорили.
Я кроме PositionSelect и копаться в истории сделок никаких проверок не знаю. Как то крутил PositionSelect в цикле и через пол дня он дал сбой. Может есть альтернатива попроще хистори?
Зачем крутить PositionSelect в цикле? Если нужно следить только за текущим символом, то достаточно:
if (PositionSelect(_Symbol)) { // Есть позиция по символу - аналог tradeResult != 0 if (OrderGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { // Длинная позиция, аналог tradeResult = 1 } else { // Короткая позиция, аналог tradeResult = 2 } }
Это верный способ существования позиции. Но еще нужно обдумать, как действовать после отсылки запроса о закрытии позиции, чтобы не отправлять новые приказы закрытия, пока не придет ответ от сервера. Смотрите в сторону OnTrade() и OnTradeTransaction().
Зачем крутить PositionSelect в цикле? Если нужно следить только за текущим символом, то достаточно:
Это верный способ существования позиции. Но еще нужно обдумать, как действовать после отсылки запроса о закрытии позиции, чтобы не отправлять новые приказы закрытия, пока не придет ответ от сервера. Смотрите в сторону OnTrade() и OnTradeTransaction().

- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Добрый день.
Пишу робота для ФОРТСа и заметил что после открытия ордера прибыль оказывается положительной а робот этого не замечает или замечает через раз.
В чем может быть дело?
Заранее спасибо.
Код: