Здравствуйте, я еще совсем новичок впрограммировании наMQL5 и застрял на написании кода для советника по сетке. В принципе, я хочу, чтобы советник делал следующее:
Шаг 1. Если нет открытых позиций и отложенных ордеров, советник должен вызвать функцию OpenNewTrade()
Шаг 2. Если есть открытые позиции или отложенные ордера, советник должен закрыть все остальные позиции на продажу и удалить все лимитные ордера на покупку, когда позиция на продажу достигнет тейк-профита. Также он должен закрывать все остальные позиции на покупку и удалять все лимитные ордера на продажу, когда позиция на покупку достигает тейк-профита.
Шаг 3. Если шаг 2 выполнен правильно, то открытых позиций и отложенных ордеров больше не будет, поэтому шаг 1 вызывается снова в цикле.
ПРОБЛЕМА
==========
Все функции работают нормально, за исключением того, что функция закрытия позиций, как в шаге 2 выше, не работает должным образом, поэтому я не знаю, есть ли ошибка в логике кода. Например, всякий раз, когда позиция на продажу достигает тейк-профита, лимитные ордера на покупку удаляются корректно, но другая позиция (позиции) на продажу удаляется вместе с позицией (позициями) на покупку. Так не должно быть, поскольку я хочу, чтобы советник работал строго в соответствии с шагом 2. Ниже приведен код советника:
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\OrderInfo.mqh>
#include <Expert\Money\MoneyFixedMargin.mqh>
//-------
CPositionInfo m_position;
CTrade trade;
CSymbolInfo m_symbol;
CAccountInfo m_account;
CDealInfo m_deal;
COrderInfo m_order;
CMoneyFixedMargin *m_money;
//--------bool m_need_close_all_buy = false;
bool m_need_close_all_sell = false;
bool m_need_delete_all_buy = false;
bool m_need_delete_all_sell = false;
//--------inputdouble FirstLot = 0.01;
inputint TakeProfitPoints = 20;
inputint GridLevelBuy = 3;
inputint GridLevelSell = 3;
inputint GridDistancePoints = 20;
inputint InpMagic = 123456;
//-------voidOnInit()
{
trade.SetExpertMagicNumber(InpMagic);
}
//-------voidOnDeinit(constint reason)
{
}
//-------voidOnTick()
{
if(m_need_close_all_buy)
{
CloseAllBuyPositions();
}
//----if(m_need_close_all_sell)
{
CloseAllSellPositions();
}
//---if(m_need_delete_all_buy)
{
DeleteAllPendingBuyOrders();
}
//---if(m_need_delete_all_sell)
{
DeleteAllPendingSellOrders();
}
//---if(PositionsTotal() == 0 && OrdersTotal() == 0)
{
OpenNewTrades();
}
}
//+------------------------------------------------------------------+//| TradeTransaction function |//+------------------------------------------------------------------+voidOnTradeTransaction(constMqlTradeTransaction &trans,
constMqlTradeRequest &request,
constMqlTradeResult &result)
{
//--- get transaction type as enumeration valueENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in historyif(type==TRADE_TRANSACTION_DEAL_ADD)
{
if(HistoryDealSelect(trans.deal))
{
m_deal.Ticket(trans.deal);
if(m_deal.DealType() == DEAL_TYPE_SELL &&
(m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
{
long deal_reason = -1;
if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
{
if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
{
// Close all sell positions
m_need_close_all_sell=true;//---------------------------------------------This is the line of code that wont execute properly// Delete all pending buy orders
m_need_delete_all_buy=true;
}
}
}
if(m_deal.DealType() == DEAL_TYPE_BUY &&
(m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
{
long deal_reason = -1;
if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
{
if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
{
// Close all buy positions
m_need_close_all_buy=true;//---------------------------------------------This is the line of code that wont execute properly// Delete all pending sell orders
m_need_delete_all_sell=true;
}
}
}
}
}
}
//+------------------------------------------------------------------+//| Close all positions |//+------------------------------------------------------------------+void CloseAllBuyPositions(void)
{
int totalPositions = PositionsTotal();
for(int i = PositionsTotal()-1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
string symbol = PositionGetString(POSITION_SYMBOL);
if(PositionGetInteger(POSITION_MAGIC) == InpMagic && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && symbol == _Symbol)
{
trade.PositionClose(ticket);
}
}
}
void CloseAllSellPositions(void)
{
int totalPositions = PositionsTotal();
for(int i = PositionsTotal()-1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
string symbol = PositionGetString(POSITION_SYMBOL);
if(PositionGetInteger(POSITION_MAGIC) == InpMagic && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && symbol == _Symbol)
{
trade.PositionClose(ticket);
}
}
}
//+------------------------------------------------------------------+//| Delete all pending orders |//+------------------------------------------------------------------+void DeleteAllPendingBuyOrders(void)
{
int totalOrders = OrdersTotal();
for(int i = OrdersTotal()-1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
string symbol = OrderGetString(ORDER_SYMBOL);
if(OrderGetInteger(ORDER_MAGIC) == InpMagic && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT && symbol == _Symbol)
{
trade.OrderDelete(ticket);
}
}
}
void DeleteAllPendingSellOrders(void)
{
int totalOrders = OrdersTotal();
for(int i = OrdersTotal()-1; i >= 0; i--)
{
ulong ticket = OrderGetTicket(i);
string symbol = OrderGetString(ORDER_SYMBOL);
if(OrderGetInteger(ORDER_MAGIC) == InpMagic && OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT && symbol == _Symbol)
{
trade.OrderDelete(ticket);
}
}
}
//+------------------------------------------------------------------+void OpenNewTrades()
{
double bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
double ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
double tpBuy, tpSell, buyLimitPrice, sellLimitPrice;
// Calculate take profit for initial buy and sell positions
tpBuy = ask + TakeProfitPoints * _Point;
tpSell = bid - TakeProfitPoints * _Point;
// Place initial buy position with take profit
trade.Buy(FirstLot, _Symbol, ask, 0, tpBuy);
// Place initial sell position with take profit
trade.Sell(FirstLot, _Symbol, bid, 0, tpSell);
// Place buy limit ordersfor(int i = 0; i < GridLevelBuy; i++)
{
buyLimitPrice = ask - (GridDistancePoints * (i + 1)) * _Point;
tpBuy = buyLimitPrice + TakeProfitPoints * _Point;
trade.BuyLimit(FirstLot * MathPow(2, i), buyLimitPrice, _Symbol, 0, tpBuy);
}
// Place sell limit ordersfor(int i = 0; i < GridLevelSell; i++)
{
sellLimitPrice = bid + (GridDistancePoints * (i + 1)) * _Point;
tpSell = sellLimitPrice - TakeProfitPoints * _Point;
trade.SellLimit(FirstLot * MathPow(2, i), sellLimitPrice, _Symbol, 0, tpSell);
}
}
Также я не знаю, как сделать так, чтобы советник задавал свое имя в качестве торговых комментариев. Было бы здорово, если бы вы помогли мне с этим, так как я хочу, чтобы сделки этого советника отличались от сделок других советников. Спасибо.
"Freelance" is the largest freelance service for ordering MQL4/MQL5 trading robots and technical indicators. Hundreds of professional developers are ready to develop a custom trading application for the MetaTrader 4/5 terminal.
//+------------------------------------------------------------------+//| TradeTransaction function |//+------------------------------------------------------------------+voidOnTradeTransaction(constMqlTradeTransaction &trans,
constMqlTradeRequest &request,
constMqlTradeResult &result)
{
//--- get transaction type as enumeration valueENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in historyif(type==TRADE_TRANSACTION_DEAL_ADD)
{
if(HistoryDealSelect(trans.deal))
{
m_deal.Ticket(trans.deal);
if(m_deal.DealType() == DEAL_TYPE_BUY &&
(m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
{
long deal_reason = -1;
if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
{
if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
{
// Close all sell positions
m_need_close_all_sell=true;//---------------------------------------------This is the line of code that wont execute properly// Delete all pending buy orders
m_need_delete_all_buy=true;
}
}
}
if(m_deal.DealType() == DEAL_TYPE_SELL&&
(m_deal.Entry() == DEAL_ENTRY_OUT || m_deal.Entry() == DEAL_ENTRY_INOUT))
{
long deal_reason = -1;
if(m_deal.InfoInteger(DEAL_REASON, deal_reason))
{
if((ENUM_DEAL_REASON)deal_reason == DEAL_REASON_TP)
{
// Close all buy positions
m_need_close_all_buy=true;//---------------------------------------------This is the line of code that wont execute properly// Delete all pending sell orders
m_need_delete_all_sell=true;
}
}
}
}
}
}
К тому же у вас флаг удаления позиций и ордеров, после первого удаления всегда true, так как нигде в коде вы его после удаления позиций и ордеров не делаете false.
К тому же у вас флаг удаления позиций и ордеров, после первого удаления всегда true, так как нигде в коде вы его после удаления позиций и ордеров не делаете false.
Вроде по логике, должно быть так.
Александр, а то, что эти флаги инициализированы false на глобальном уровне, разве это в счёт не идёт?
При запуске советника в MT5 Strategy Tester я постоянно получаю ошибку "failed market sell 0.01 EURUSD [Unsupported filling mode]". Код результата (retcode) возвращается 10030. Вот структура моего запроса. Пожалуйста, помогите.
Albert Mathenge #: При запуске советника в MT5 Strategy Tester я постоянно получаю ошибку "failed market sell 0.01 EURUSD [Unsupported filling mode]". Код результата (retcode) возвращается 10030. Вот структура моего запроса. Пожалуйста, помогите.
И странно, что компилятор выдает только одну ошибку. Хотя, если _Points и order_success были проинициализированы на глобальном уровне, то тогда, пардон!
И странно, что компилятор выдает только одну ошибку. Хотя, если _Points и order_success были инициализированы на глобальном уровне, то, пардон!
С уважением, Владимир.
Да, я просто заменил имена переменных для этого форума, чтобы вы не осуждали мои странные имена переменных. lol. Спасибо за предложение, но у меня раньше было ORDER_FILLING_FOK и я получал ту же ошибку. Я прочитал, что не все символы поддерживают все режимы заполнения, поэтому я изменил его на тот, что указан в исходном сообщении, чтобы убедиться, что в запросе указаны только разрешенные режимы заполнения.
Albert Mathenge #: Да, я просто заменил имена переменных для этого форума, чтобы вы не осуждали мои странные имена переменных. lol. Спасибо за предложение, но у меня раньше было ORDER_FILLING_FOK и я получал ту же ошибку. Я прочитал, что не все символы поддерживают все режимы заполнения, поэтому я изменил его на тот, что указан в исходном сообщении, чтобы убедиться, что в запросе указаны только разрешенные режимы заполнения.
SymbolInfoInteger(_Symbol,SYMBOL_FILLING_MODE) возвращает все разрешённые режимы заполнения, а указать в запросе надо один конкретный из разрешённых.
Здравствуйте, я еще совсем новичок впрограммировании наMQL5 и застрял на написании кода для советника по сетке. В принципе, я хочу, чтобы советник делал следующее:
Шаг 1. Если нет открытых позиций и отложенных ордеров, советник должен вызвать функцию OpenNewTrade()
Шаг 2. Если есть открытые позиции или отложенные ордера, советник должен закрыть все остальные позиции на продажу и удалить все лимитные ордера на покупку, когда позиция на продажу достигнет тейк-профита. Также он должен закрывать все остальные позиции на покупку и удалять все лимитные ордера на продажу, когда позиция на покупку достигает тейк-профита.
Шаг 3. Если шаг 2 выполнен правильно, то открытых позиций и отложенных ордеров больше не будет, поэтому шаг 1 вызывается снова в цикле.
ПРОБЛЕМА
==========
Все функции работают нормально, за исключением того, что функция закрытия позиций, как в шаге 2 выше, не работает должным образом, поэтому я не знаю, есть ли ошибка в логике кода. Например, всякий раз, когда позиция на продажу достигает тейк-профита, лимитные ордера на покупку удаляются корректно, но другая позиция (позиции) на продажу удаляется вместе с позицией (позициями) на покупку. Так не должно быть, поскольку я хочу, чтобы советник работал строго в соответствии с шагом 2. Ниже приведен код советника:
Также я не знаю, как сделать так, чтобы советник задавал свое имя в качестве торговых комментариев. Было бы здорово, если бы вы помогли мне с этим, так как я хочу, чтобы сделки этого советника отличались от сделок других советников. Спасибо.Подскажите начинающему. Не могу додуматься как можно преобразовать строку.
Как заменить символы в "var_1" подстроки от заданного индекса, на символы "var_2'' ?
Позиция на продажу, закрывается сделкой на покупку.
Этот код у вас проверяет закрытие позиции Sell.
m_deal.DealType() == DEAL_TYPE_BUYПопробуйте так.
К тому же у вас флаг удаления позиций и ордеров, после первого удаления всегда true, так как нигде в коде вы его после удаления позиций и ордеров не делаете false.
Вроде по логике, должно быть так.
К тому же у вас флаг удаления позиций и ордеров, после первого удаления всегда true, так как нигде в коде вы его после удаления позиций и ордеров не делаете false.
Вроде по логике, должно быть так.
Александр, а то, что эти флаги инициализированы false на глобальном уровне, разве это в счёт не идёт?
С уважением, Владимир.
Александр, а то, что эти флаги инициализированы false на глобальном уровне, разве это в счёт не идёт?
С уважением, Владимир.
Один раз false. А потом они всегда true и на каждом тике будут удалять отложенные ордера и позиции.
Один раз false. А потом они всегда true и на каждом тике будут удалять отложенные ордера и позиции.
Ну, да, логично. Спасибо за разъяснение.
С уважением, Владимир.
Вот структура моего запроса. Пожалуйста, помогите.
При запуске советника в MT5 Strategy Tester я постоянно получаю ошибку "failed market sell 0.01 EURUSD [Unsupported filling mode]". Код результата (retcode) возвращается 10030.
Вот структура моего запроса. Пожалуйста, помогите.
Попробуйте поменять строку
на строку
request.type_filling = ORDER_FILLING_FOK;И странно, что компилятор выдает только одну ошибку. Хотя, если _Points и order_success были проинициализированы на глобальном уровне, то тогда, пардон!
С уважением, Владимир.
Попробуйте изменить строку
на строку
И странно, что компилятор выдает только одну ошибку. Хотя, если _Points и order_success были инициализированы на глобальном уровне, то, пардон!
С уважением, Владимир.
Спасибо за предложение, но у меня раньше было ORDER_FILLING_FOK и я получал ту же ошибку. Я прочитал, что не все символы поддерживают все режимы заполнения, поэтому я изменил его на тот, что указан в исходном сообщении, чтобы убедиться, что в запросе указаны только разрешенные режимы заполнения.
Да, я просто заменил имена переменных для этого форума, чтобы вы не осуждали мои странные имена переменных. lol.
Спасибо за предложение, но у меня раньше было ORDER_FILLING_FOK и я получал ту же ошибку. Я прочитал, что не все символы поддерживают все режимы заполнения, поэтому я изменил его на тот, что указан в исходном сообщении, чтобы убедиться, что в запросе указаны только разрешенные режимы заполнения.
SymbolInfoInteger(_Symbol,SYMBOL_FILLING_MODE) возвращает все разрешённые режимы заполнения, а указать в запросе надо один конкретный из разрешённых.