#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リカ
タラス・スロボダニク さん 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リカ
マキシム・クズネツォフ, 2017.02.24 22:20
Suddenly, StringFormat, PrintFormat :-).PrintFormat("16進数 %xと8進数 %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() の後、オーダーは常に履歴に残ります。
真実を明らかにしよう。私は考える時間があったので、放置することにしたのですが、私の疑念を払拭するためにお願いしてお願いしたVitya(Vinin)も、(削除に対する私の疑念を確認して)議論から離れることを提案しました--真実が生まれるように。それが正しいことだと思うんです。とにかく後で集計を開始し、埋まり次第ここに掲載する予定です。
真実を明らかにしよう...。
アルチョム!
あなたは合理的で政治的に正しい人だ!
どんな真実?よくご存じですね。
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をプログラムに使用すればよいのです。