Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
А то ж, если будем ругаться-препираться, то из полезной темы мы скатимся в несколько страниц препираний. Потом всё чистить, чтобы осталась суть... Вот именно хотелось бы, чтобы здесь отображалась именно суть того, или иного процесса. Пусть будут несколько вариантов какой-либо реализации чего-либо. Можно будет обсудить достоинства и недостатки каждого метода.
Потом, когда накопится достаточно разной полезной информации, есть мысль аккумулировать всё это в табличку. И постоянно её пополнять при накоплении очередных полезных фишек.
Думаю - полезно будет от этого всем.
Ответы:
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("Шестнадцатиричное %x и восьмиричное %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(), кому-то появления ордера или сделка в списке. Для примера - отличие от МТ4. В М4, после OrderSend() ордер уже есть в списке ордеров, а после OrderClose() всегда есть в истории.
Давайте дадим найти истину. Время было обдумать, и решил всё же оставить, да и Витя (Vinin) у коего я поинтересовался и попросил развеять мои сомнения, тоже предложил оставить обсуждение (подтвердив мои сомнения в удалении) - пусть истина родится. Думаю, так правильней будет. Всё равно позже собираюсь начать в табличку собирать, чтобы её здесь прикладывать по мере её наполнения.
Давайте дадим найти истину...
Артём!
Вы разумный и политкорректный человек!
Какую истину? Вы-то прекрасно понимаете о чём идёт речь.
fxsaber написал скрипт (неплохой), но никто его не похвалил, вот он и
пытается в каждой теме напомнить о нём.
Хвалю - молодец!
Но вот беда, в эгом скрипте нельзя использовать OnTradeTransaction, вот и приходится из "г-на шарики катать" (типа Sleep или другой таймер)
Ну и естественно "забота" о других пользователях, которые ещё не знают, что СКРИПТ - лучше СОВЕТНИКА!
А Dmitry Fedoseev апроиоре всегда против того, что я скажу и не важно прав я или нет.
Истину здесь не найти, потому что не ДЕЛО, а ЛИЧНОЕ выходит на передний план.
{
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-файла и в своих программах делать соответствующий #include.