#define WHILE(A) while ((!(Res = (A))) && ORDERSEND::Waiting())
public: staticuint OrderSend_MaxPause; // максимальное время на синхронизацию в мкс.
// Полностью синхронизированный с торговым окружением OrderSend. // По окончании работы ГАРАНТИРОВАННО и за МИНИМАЛЬНОЕ время доступно корректное торговое окружение. // По скорости ничем не уступает связке OrderSendAsync + OnTradeTransaction. // Учтены MT5-нюансы: Result.deal == 0, STATE_STARTED и STATE_MODIFY pending. // В тестере/оптимизаторе производительность равна штатной OrderSend. staticbool OrderSendSync( constMqlTradeRequest &Request, MqlTradeResult &Result ) { constulong StartTime1 = ::GetMicrosecondCount();
否则,如果我们争论,我们会从有用的话题变成几页的争吵。然后我们要把它全部清理干净,留下它的精华......确切地说,我想知道这个或那个过程的本质。让某些东西的实现有几个版本。将有可能讨论每种方法的优点和缺点。
然后,当积累了足够多不同的有用信息后,就有了将其全部积累到一个表中的想法。并在积累下一个有用的筹码时不断补充。
我想这对每个人都会有帮助。
答案。
1.
关于交易、自动交易系统和测试交易策略的论坛
8和16里卡
Taras Slobodyanik, 2017.02.24 22:16
{
string s = "", c;
while(n != 0)
{
if(n%16<10)
c=CharToStr(n%16+'0');
else
c=CharToStr(n%16+'A'-10);
s = c + s;
n = n / 16;
}
return(s);
}
关于交易、自动交易系统和测试交易策略的论坛
8和16里卡
Maxim Kuznetsov, 2017.02.24 22:20
突然,StringFormat,PrintFormat :-)PrintFormat("Hex %x and octal %o",1122,1122)。
关于交易、自动交易系统和测试交易策略的论坛
8和16里卡
fxsaber, 2017.02.24 22:21
{
static const string digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "K",
"L", "M", "N", "O", "P", "Q", "R", "S", "T", "V", "X", "Y", "Z"};
string Str = (Num == 0) ? "0" : "";
while (Num > 0)
{
Str = digits[Num % Scale] + Str;
Num /= Scale;
}
return(Str);
}
void OnStart()
{
Print(NumToString(123, 8));
Print(NumToString(123, 16));
}
你真的相信一个成熟的交易机器人可以用脚本来写吗?
把对fxsaber和prostotrader同志的讨论移到另一个主题,如果这里有讨论,这个主题将失去实际意义。当他们想出一个真正的解决方案时,他们会在这里发布。而在我看来,这不应该是怀疑或研究的一个分支。它应该是一个实际解决方案的分支。如果有几个人对这个问题有不同的看法--就让他们在其他地方讨论吧。
<要删除的帖子
你不需要等待几毫秒的时间。
该信息将在OnTradeTransaction 中出现
见代码
你的信息的重点是什么?它将在OnTradeTransaction()中到达,所以呢? 这意味着我们必须等待事件。我们还是要等待。fxsaber的意思是,在OrderSend()被执行后,所执行的动作的信息不会立即出现在终端。有些人喜欢等待OnTradeTransaction(),而有些人则喜欢在列表中看到订单或交易。以下是与MT4的区别,作为一个例子。在M4中,在OrderSend()之后,订单已经在订单列表中,而在OrderClose()之后,订单一直在历史中。
让我们让真相被发现。我有时间想了想,决定离开它,我问了又问的维提亚(Vinin)也建议离开讨论(证实了我对删除的怀疑)--让真理诞生。我认为这将是正确的做法。我打算以后开始制表,当它填满时就在这里公布。
让我们发现真相......
Artyom!
你是一个通情达理、政治正确的人!
什么真相?你完全知道我们在说什么。
fxsaber写了一个剧本(还不错),但没有人称赞它,所以他
试图在每个主题中提醒它。
干得好!
但问题来了,你不能在这个脚本中使用OnTradeTransaction,所以他必须从 "OnTradeTransaction先生 "那里 "滚球"(如睡眠或其他计时器)。
当然,还要 "关心 "其他用户,他们还不知道SCRIPT比COUNTER好。
德米特里-费多塞耶夫 总是反对我说的话,不管我是对还是错。
在这里不能找到真理,因为它不是一个原因,而是一个个人的原因,这一点凸显出来。
{
private:
static const bool IsTester;
static bool Waiting( const bool FlagInit = false )
{
static ulong StartTime = 0;
const bool Res = FlagInit ? false : (::GetMicrosecondCount() - StartTime < ORDERSEND::OrderSend_MaxPause);
if (FlagInit)
StartTime = ::GetMicrosecondCount();
else if (Res)
::Sleep(0);
return(Res);
}
static bool EqualPrices( const double Price1, const double Price2, const int digits)
{
return(::NormalizeDouble(Price1 - Price2, digits) == 0);
}
static bool HistoryDealSelect( MqlTradeResult &Result )
{
if ((Result.deal == 0) && (Result.order != 0))
{
if (::HistorySelectByPosition(::HistoryOrderGetInteger(Result.order, ORDER_POSITION_ID)))
for (int i = ::HistoryDealsTotal() - 1; i >= 0; i--)
{
const ulong DealTicket = ::HistoryDealGetTicket(i);
if (Result.order == ::HistoryDealGetInteger(DealTicket, DEAL_ORDER))
{
Result.deal = DealTicket;
break;
}
}
}
return(::HistoryDealSelect(Result.deal));
}
#define TMP_ORDERSEND_BENCHMARK(A) \
static ulong Max##A = 0; \
\
if (Interval##A > Max##A) \
{ \
ORDERSEND_BENCHMARK \
\
Max##A = Interval##A; \
}
static void OrderSend_Benchmark( const ulong Interval1, const ulong Interval2 = 0 )
{
#ifdef ORDERSEND_BENCHMARK
TMP_ORDERSEND_BENCHMARK(1)
TMP_ORDERSEND_BENCHMARK(2)
#endif // ORDERSEND_BENCHMARK
return;
}
#undef TMP_ORDERSEND_BENCHMARK
#define WHILE(A) while ((!(Res = (A))) && ORDERSEND::Waiting())
public:
static uint OrderSend_MaxPause; // максимальное время на синхронизацию в мкс.
// Полностью синхронизированный с торговым окружением OrderSend.
// По окончании работы ГАРАНТИРОВАННО и за МИНИМАЛЬНОЕ время доступно корректное торговое окружение.
// По скорости ничем не уступает связке OrderSendAsync + OnTradeTransaction.
// Учтены MT5-нюансы: Result.deal == 0, STATE_STARTED и STATE_MODIFY pending.
// В тестере/оптимизаторе производительность равна штатной OrderSend.
static bool OrderSendSync( const MqlTradeRequest &Request, MqlTradeResult &Result )
{
const ulong StartTime1 = ::GetMicrosecondCount();
bool Res = ::OrderSend(Request, Result);
const ulong Interval1 = ::GetMicrosecondCount() - StartTime1;
const ulong StartTime2 = ::GetMicrosecondCount();
if (Res && !ORDERSEND::IsTester && (Result.retcode < TRADE_RETCODE_ERROR) && (ORDERSEND::OrderSend_MaxPause > 0))
{
Res = (Result.retcode == TRADE_RETCODE_DONE);
ORDERSEND::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(ORDERSEND::HistoryDealSelect(Result))
;
}
else if (Request.action == TRADE_ACTION_PENDING)
{
if (Res)
WHILE(::OrderSelect(Result.order) && ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) == ORDER_STATE_PLACED))
;
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 = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
EqualTP = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
}
WHILE((EqualSL && EqualTP))
if ((Request.position == 0) ? ::PositionSelect(Request.symbol) : ::PositionSelectByTicket(Request.position))
{
EqualSL = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_SL), Request.sl, digits);
EqualTP = ORDERSEND::EqualPrices(::PositionGetDouble(POSITION_TP), Request.tp, digits);
}
}
}
else if (Request.action == TRADE_ACTION_MODIFY)
{
if (Res)
{
bool EqualSL = false;
bool EqualTP = false;
bool EqualPrice = false;
const int digits = (int)::SymbolInfoInteger(Request.symbol, SYMBOL_DIGITS);
if (::OrderSelect(Result.order))
{
EqualSL = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
EqualTP = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
EqualPrice = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_PRICE_OPEN), Request.price, digits);
}
WHILE((EqualSL && EqualTP && EqualPrice))
if (::OrderSelect(Result.order) && ((ENUM_ORDER_STATE)::OrderGetInteger(ORDER_STATE) != ORDER_STATE_REQUEST_MODIFY))
{
EqualSL = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_SL), Request.sl, digits);
EqualTP = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_TP), Request.tp, digits);
EqualPrice = ORDERSEND::EqualPrices(::OrderGetDouble(ORDER_PRICE_OPEN), Request.price, digits);
}
}
}
else if (Request.action == TRADE_ACTION_REMOVE)
if (Res)
WHILE(::HistoryOrderSelect(Result.order))
;
}
const ulong Interval2 = ::GetMicrosecondCount() - StartTime2;
Result.comment += " " + ::DoubleToString(Interval1 / 1000.0, 3) + " + " + ::DoubleToString(Interval2 / 1000.0, 3) + " ms";
ORDERSEND::OrderSend_Benchmark(Interval1, Interval2);
return(Res);
}
#undef WHILE
};
static const bool ORDERSEND::IsTester = (::MQLInfoInteger(MQL_TESTER) || ::MQLInfoInteger(MQL_OPTIMIZATION) ||
::MQLInfoInteger(MQL_VISUAL_MODE) || ::MQLInfoInteger(MQL_FRAME_MODE));
static uint ORDERSEND::OrderSend_MaxPause = 1000000; // максимальное время на синхронизацию в мкс.
// Эта строчка позволяет сделать все OrderSend корректными.
#define OrderSend ORDERSEND::OrderSendSync
一切都被刻意包裹在教室里,以减少潜在问题的数量。
使用
也就是说,要使所有的OrderSend 与交易环境同步,避免陷阱,只需将这段源代码写成mqh-file,并在程序中使用相应的#include即可。