// Подсчет комиссий и свопов указанной позиции по символу double PosTotalCommissSwap (string symb, bool commiss, bool swap) { int posTotal = PositionsTotal (); //всего открытых позиций Print (posTotal);
//пройдем по всем открытым позициям for(int i = posTotal - 1; i >=0; i--) { string posSymb = PositionGetSymbol (i); Print (posSymb);
//если найдена позиция по указанному символу if(symb == posSymb) { Print ("Позиция найдена"); long posID = PositionGetInteger (POSITION_IDENTIFIER);
//выберем историю сделок, относящуюся к выбранной позиции if(HistorySelectByPosition (posID)) { int dealsTotal = HistoryDealsTotal (); //всего сделок в истории позиции Print ("Всего сделок в позиции: " + dealsTotal); double fees = 0.0; //все комиссии и свопы
//пройдем по всем сделкам позиции for(int k = 0; k < dealsTotal; k++) { ulong dealTicket = HistoryDealGetTicket (k); //тикет сделки
fxsaber: Если это происходит после OrderSend, то нормально.
Нет, это никак не нормально. В любом случае позиция есть, а значит и есть сделки которые участвовали в её "жизни". Но более странно то, что сделки код не видит даже если кинуть советник уже при наличии позиции, это мы и видим по логам, определено количество позиций, выбрана позиция по символу, а сделок в ней нет...
Andrey Dik: Нет, это никак не нормально. В любом случае позиция есть, а значит и есть сделки которые участвовали в её "жизни". Но более странно то, что сделки код не видит даже если кинуть советник уже при наличии позиции...
Ренат говорит, что это нормально, не спорьте! Вот решение для OrderSend
Да никак нельзя определить. SL и TP - сущность исключительно MT-сервера.
Вот так работает:
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
if(trans.type==TRADE_TRANSACTION_DEAL_ADD)
{
datetime end=TimeCurrent();
datetime start=end-end%PeriodSeconds(PERIOD_D1);
ResetLastError();
if(!HistorySelect(start,end))
{
Print("Getting deals history failed. Error ",GetLastError());
return;
}
ulong ticket=HistoryDealGetTicket(HistoryDealsTotal()-1);
if(ticket==trans.deal)
{
if(HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT &&
(StringFind(HistoryDealGetString(ticket,DEAL_COMMENT),"tp")!=-1
|| StringFind(HistoryDealGetString(ticket,DEAL_COMMENT),"sl")!=-1))
{
Print(HistoryDealGetString(ticket,DEAL_SYMBOL)," Profit= ",HistoryDealGetDouble(ticket,DEAL_PROFIT)," ticket=",ticket);
}
}
}
}
{
if ((Trans.type == TRADE_TRANSACTION_ORDER_ADD) &&
PositionSelectByTicket(Trans.position) && OrderSelect(Trans.order) &&
(PositionGetInteger(POSITION_TYPE) == 1 - OrderGetInteger(ORDER_TYPE)))
{
const double Price = OrderGetDouble(ORDER_PRICE_OPEN);
if (Price == PositionGetDouble(POSITION_TP))
Print("Position #" + (string)Trans.position + " - triggered TP.");
else if (Price == PositionGetDouble(POSITION_SL))
Print("Position #" + (string)Trans.position + " - triggered SL.");
}
}
Рабочий вариант для реала (не для тестера)
{
if ((Trans.type == TRADE_TRANSACTION_ORDER_ADD) &&
PositionSelectByTicket(Trans.position) && OrderSelect(Trans.order) &&
(PositionGetInteger(POSITION_TYPE) == 1 - OrderGetInteger(ORDER_TYPE)))
{
const double Price = OrderGetDouble(ORDER_PRICE_OPEN);
if (Price == PositionGetDouble(POSITION_TP))
Print("Position #" + (string)Trans.position + " - triggered TP.");
else if (Price == PositionGetDouble(POSITION_SL))
Print("Position #" + (string)Trans.position + " - triggered SL.");
}
}
Проверил в тестере - не работает, думаю и на реале работать не будет, поскольку позиции по которой идет проверка уже не существует.
{
string s = DoubleToString(PosTotalCommissSwap (Symbol (), true, true), 4);
Comment (s);
}
//+------------------------------------------------------------------+
// Подсчет комиссий и свопов указанной позиции по символу
double PosTotalCommissSwap (string symb, bool commiss, bool swap)
{
int posTotal = PositionsTotal (); //всего открытых позиций
Print (posTotal);
//пройдем по всем открытым позициям
for(int i = posTotal - 1; i >=0; i--)
{
string posSymb = PositionGetSymbol (i);
Print (posSymb);
//если найдена позиция по указанному символу
if(symb == posSymb)
{
Print ("Позиция найдена");
long posID = PositionGetInteger (POSITION_IDENTIFIER);
//выберем историю сделок, относящуюся к выбранной позиции
if(HistorySelectByPosition (posID))
{
int dealsTotal = HistoryDealsTotal (); //всего сделок в истории позиции
Print ("Всего сделок в позиции: " + dealsTotal);
double fees = 0.0; //все комиссии и свопы
//пройдем по всем сделкам позиции
for(int k = 0; k < dealsTotal; k++)
{
ulong dealTicket = HistoryDealGetTicket (k); //тикет сделки
if(commiss)
fees += HistoryDealGetDouble (dealTicket, DEAL_COMMISSION);
if(swap)
fees += HistoryDealGetDouble (dealTicket, DEAL_SWAP);
}
return (fees);
}
else
Print ("Историю сделок выбрать не удалось");
}
}
return (0.0);
}
Похоже поломался выбор истории сделок по идентификатору позиции.
Принт иногда (а иногда и нет) пишет
2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) 1
2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) GBPUSD
2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) Позиция найдена
2016.12.05 11:26:11.767 Get current commission of pos (GBPUSD,M5) Всего сделок в позиции: 0
Похоже поломался выбор истории сделок по идентификатору позиции.
Если это происходит после OrderSend, то нормально.
Нет, это никак не нормально. В любом случае позиция есть, а значит и есть сделки которые участвовали в её "жизни". Но более странно то, что сделки код не видит даже если кинуть советник уже при наличии позиции...
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Как правильно работать в MT5 с OrderSend
fxsaber, 2016.11.19 23:59
Выдрал из библиотеки сюда синхронизированный OrderSendSyncconst bool IsTester = (::MQLInfoInteger(MQL_TESTER) || ::MQLInfoInteger(MQL_OPTIMIZATION) ||
::MQLInfoInteger(MQL_VISUAL_MODE) || ::MQLInfoInteger(MQL_FRAME_MODE));
bool Waiting( const bool FlagInit = false )
{
static ulong StartTime = 0;
if (FlagInit)
StartTime = ::GetMicrosecondCount();
const bool Res = (::GetMicrosecondCount() - StartTime < OrderSend_MaxPause);
if (Res)
::Sleep(0);
return(Res);
}
bool EqualPrices( const double Price1, const double Price2, const int digits)
{
return(::NormalizeDouble(Price1 - Price2, digits) == 0);
}
#define WHILE(A) while (!(Res = (A)) && Waiting())
bool OrderSendSync( const MqlTradeRequest &Request, MqlTradeResult &Result )
{
bool Res = ::OrderSend(Request, Result);
if (Res && !IsTester && (Result.retcode < TRADE_RETCODE_ERROR) && (OrderSend_MaxPause > 0))
{
Res = (Result.retcode == TRADE_RETCODE_DONE);
Waiting(true);
if (Request.action == TRADE_ACTION_DEAL)
{
WHILE(::HistoryOrderSelect(Result.order))
;
Res = Res && (((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_FILLED) ||
((ENUM_ORDER_STATE)::HistoryOrderGetInteger(Result.order, ORDER_STATE) == ORDER_STATE_PARTIAL));
if (Res)
WHILE(::HistoryDealSelect(Result.deal))
;
}
else if (Request.action == TRADE_ACTION_PENDING)
{
if (Res)
WHILE(::OrderSelect(Result.order))
;
else
{
WHILE(::HistoryOrderSelect(Result.order))
;
Res = false;
}
}
else if (Request.action == TRADE_ACTION_SLTP)
{
if (Res)
{
bool EqualSL = false;
bool EqualTP = false;
const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);
if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
{
EqualSL = EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
EqualTP = EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
}
WHILE((EqualSL && EqualTP))
if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
{
EqualSL = EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
EqualTP = EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
}
}
}
else if (Request.action == TRADE_ACTION_MODIFY)
{
if (Res)
{
bool EqualSL = false;
bool EqualTP = false;
const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);
if (::OrderSelect(Result.order))
{
EqualSL = EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
EqualTP = EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
}
WHILE((EqualSL && EqualTP))
if (::OrderSelect(Result.order))
{
EqualSL = EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
EqualTP = EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
}
}
}
else if (Request.action == TRADE_ACTION_REMOVE)
if (Res)
WHILE(::HistoryOrderSelect(Result.order))
;
}
return(Res);
}
#undef WHILE
Если будете использовать этот OrderSend, то проблем таких не возникнет.
Либо ждите соответствующих сообщений в OnTradeTransaction.
Ренат говорит, что это нормально, не спорьте! Вот решение для OrderSend
Если будете использовать этот OrderSend, то проблем таких не возникнет.
Либо ждите соответствующих сообщений в OnTradeTransaction.
Да нет же, это ненормально.
Позиция есть. Кидаем советник на чарт. Истории сделок по выбранной позиции нет. Что же тут нормального то?)))