Что с того, что какой-то режим не поддерживается? С чего вдруг от этого запрещать себе торговлю?
Особенно если "не поддерживает Stop Limit режим установки ордеров"? Вот это беда вообще невероятная, не дающая возможности торговать.
© РАЗРУХА В ГОЛОВАХ
В самом начале написано:
ВАЖНО: Чтобы не "растягивать" топик, при возникновении замечаний,
или есть вопросы - создать в этом разделе отдельную тему (здесь отвечать не буду).
P/S Для особо "одарённых" :
В этой функции необходимо проверять те параметры, которые
Вы будете использовать в своём советнике. Вот пример:
.......................
Продолжение:
Часто используемые и полезные функции:
Сама функция CheckError() (в примере не все коды возврата)
.........................................................................
Расшифровка кодов возврата:
string GetRetCode( const uint code ) { string retcode; switch( code ) { case TRADE_RETCODE_REQUOTE: retcode = "Реквота"; break; case TRADE_RETCODE_REJECT: retcode = "Запрос отвергнут"; break; case TRADE_RETCODE_CANCEL: retcode = "Запрос отменен трейдером"; break; case TRADE_RETCODE_PLACED: retcode = "Ордер размещен"; break; case TRADE_RETCODE_DONE: retcode = "Заявка выполнена"; break; case TRADE_RETCODE_DONE_PARTIAL: retcode = "Заявка выполнена частично"; break; case TRADE_RETCODE_ERROR: retcode = "Ошибка обработки запроса"; break; case TRADE_RETCODE_TIMEOUT: retcode = "Запрос отменен по истечению времени"; break; case TRADE_RETCODE_INVALID: retcode = "Неправильный запрос"; break; case TRADE_RETCODE_INVALID_VOLUME: retcode = "Неправильный объем в запросе"; break; case TRADE_RETCODE_INVALID_PRICE: retcode = "Неправильная цена в запросе"; break; case TRADE_RETCODE_INVALID_STOPS: retcode = "Неправильные стопы в запросе"; break; case TRADE_RETCODE_TRADE_DISABLED: retcode = "Торговля запрещена"; break; case TRADE_RETCODE_MARKET_CLOSED: retcode = "Рынок закрыт"; break; case TRADE_RETCODE_NO_MONEY: retcode = "Нет достаточных денежных средств для выполнения запроса"; break; case TRADE_RETCODE_PRICE_CHANGED: retcode = "Цены изменились"; break; case TRADE_RETCODE_PRICE_OFF: retcode = "Отсутствуют котировки для обработки запроса"; break; case TRADE_RETCODE_INVALID_EXPIRATION: retcode = "Неверная дата истечения ордера в запросе"; break; case TRADE_RETCODE_ORDER_CHANGED: retcode = "Состояние ордера изменилось"; break; case TRADE_RETCODE_TOO_MANY_REQUESTS: retcode = "Слишком частые запросы"; break; case TRADE_RETCODE_NO_CHANGES: retcode = "В запросе нет изменений"; break; case TRADE_RETCODE_SERVER_DISABLES_AT: retcode = "Автотрейдинг запрещен сервером"; break; case TRADE_RETCODE_CLIENT_DISABLES_AT: retcode = "Автотрейдинг запрещен клиентским терминалом"; break; case TRADE_RETCODE_LOCKED: retcode = "Запрос заблокирован для обработки"; break; case TRADE_RETCODE_FROZEN: retcode = "Ордер или позиция заморожены"; break; case TRADE_RETCODE_INVALID_FILL: retcode = "Указан неподдерживаемый тип исполнения ордера по остатку"; break; case TRADE_RETCODE_CONNECTION: retcode = "Нет соединения с торговым сервером"; break; case TRADE_RETCODE_ONLY_REAL: retcode = "Операция разрешена только для реальных счетов"; break; case TRADE_RETCODE_LIMIT_ORDERS: retcode = "Достигнут лимит на количество отложенных ордеров"; break; case TRADE_RETCODE_LIMIT_VOLUME: retcode = "Достигнут лимит на объем ордеров и позиций для данного символа"; break; case TRADE_RETCODE_INVALID_ORDER: retcode = "Неверный или запрещённый тип ордера"; break; case TRADE_RETCODE_POSITION_CLOSED: retcode = "Позиция с указанным POSITION_IDENTIFIER уже закрыта"; break; default: retcode = "Нет кода возврата."; break; } return( retcode ); }
Рекомендация:
При проектировании советников для ФОРТС не рекомендую использовать событие Tick, а
лучше воспользоваться событием BookEvent
Примеры:
Добавление стакана:
(Использовать ТОЛЬКО в OnInit() )
if ( !MarketBookAdd( _Symbol ) ) { MessageBox( "Не добавлен стакан фьючерса " + _Symbol + "!", "Ошибка", MB_OK | MB_ICONHAND ); return( INIT_FAILED ); }
Удаление подписки на стакан:
void OnDeinit( const int reason ) { MarketBookRelease( _Symbol ); }
Получение лучшего ASK и BID и их объёмов из стакана цен:
double sell_price, buy_price; long sell_volume, buy_volume; //+------------------------------------------------------------------+ //| Expert Get Stakan values function | //+------------------------------------------------------------------+ bool GetStakanValues( const string aSymbol, double &sell_price, double &buy_price, long &sell_volume, long &buy_volume ) { MqlBookInfo book_price[]; buy_price = 0; sell_price = DBL_MAX; buy_volume = 0; sell_volume = 0; //--- Get stakan if ( MarketBookGet( aSymbol, book_price ) )//getBook ) { int size = ArraySize( book_price ); //--- if ( size > 0 ) { double a_min_price = SymbolInfoDouble( aSymbol, SYMBOL_SESSION_PRICE_LIMIT_MIN ); double a_max_price = SymbolInfoDouble( aSymbol, SYMBOL_SESSION_PRICE_LIMIT_MAX ); //--- for( int i = 0; i < size; i++ ) { if ( book_price[i].type == BOOK_TYPE_SELL ) { if ( book_price[i].price < sell_price ) { sell_price = book_price[i].price; sell_volume = book_price[i].volume; } } else if ( book_price[i].type == BOOK_TYPE_BUY ) //First buy - exit { buy_price = book_price[i].price; buy_volume = book_price[i].volume; break; } } if ( ( buy_price <= a_max_price ) && ( buy_price >= a_min_price ) && ( sell_price <= a_max_price ) && ( sell_price >= a_min_price ) ) { if ( sell_price == DBL_MAX ) sell_price = 0; //--- if ( ( sell_price > 0 ) && ( buy_price > 0 ) ) { return( true ); } } } } //--- if ( sell_price == DBL_MAX ) sell_price = 0; //--- return( false); }
Вызов функции:
Проверка if ( a_symbol == _Symbol ) ОБЯЗАТЕЛЬНА, она гарантирует, что изменился именно Ваш стакан цен.
//+------------------------------------------------------------------+ //| Expert On Book event function | //+------------------------------------------------------------------+ void OnBookEvent( const string &a_symbol ) { if ( a_symbol == _Symbol ) { if ( GetStakanValues( _Symbol, sell_price, buy_price, sell_volume, buy_volume ) ) { //you code } } }
СПАСИБО!!!)
Особенности:
Формулы расчёта и начисление баллов за неэффектвные и ошибочные
транзакции во вложении.
P/S Достаточно часто изменяются и правила и баллы :(
Часто используемые и полезные функции:
Функция SetStDayTime() возвращает время начала торгового дня(на момент запроса).
Функция GetExgangeFee() возвращает комиссию биржи и кол-во сделок за торговый день (на момент запроса):
//+------------------------------------------------------------------+ //| Tr_fee.mq5 | //| Copyright 2015, Mikalas | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Mikalas" #property link "https://www.mql5.com" #property version "1.00" // input long TrPoint = 1; //Балл за транзакцию input long DealPoint = 40; //Балл за сделку // datetime start_day_time; // //+------------------------------------------------------------------+ //| Expert Set start day time function | //+------------------------------------------------------------------+ datetime SetStDayTime() { MqlDateTime dt_str; TimeTradeServer( dt_str ); //--- if ( ( dt_str.day_of_week == 0 ) || ( dt_str.day_of_week == 6 ) ) return( datetime( 0 ) ); //--- string time_str = IntegerToString( dt_str.year ) + "." + IntegerToString( dt_str.mon ) + "." + IntegerToString( dt_str.day ) + " 19:00:00"; ulong cur_day = ulong( StringToTime( time_str ) ); if ( ( dt_str.hour >= 19 ) && ( dt_str.hour <= 23 ) ) { return( StringToTime( time_str ) ); } else { ulong one_day = 24 * 60 * 60; //--- if ( dt_str.day_of_week == 1 ) { cur_day -= one_day * 3; } else { cur_day -= one_day; } return( datetime( cur_day ) ); } return( datetime( 0 ) ); } //+------------------------------------------------------------------+ //| Expert calc deals fee function | //+------------------------------------------------------------------+ double GetExgangeFee( const datetime start_time, long& deals ) { double all_fee = 0.0; ulong deal_ticket; deals = 0; //--- if ( HistorySelect( start_time, TimeTradeServer() ) ) { int deals_total = HistoryDealsTotal(); //--- if ( deals_total > 0 ) { for ( uint i = 0; i < uint( deals_total ); i++ ) { deal_ticket = HistoryDealGetTicket( i ); //--- if ( deal_ticket > 0 ) { ulong order_ticket = ulong( HistoryDealGetInteger( deal_ticket, DEAL_ORDER ) ); if ( order_ticket > 0 ) { deals++; all_fee += HistoryDealGetDouble( deal_ticket, DEAL_COMMISSION ); } } } return( MathAbs( all_fee ) ); } } return( 0 ); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { long a_deals; start_day_time = SetStDayTime(); //--- if ( ulong( start_day_time ) == 0 ) { MessageBox( "Не установлено время начала торгового дня!", "Ошибка", MB_OK | MB_ICONHAND ); return( INIT_FAILED ); } Print( "Exgange Fee = ", GetExgangeFee( start_day_time, a_deals ), "; Deals = ", a_deals ); return( INIT_SUCCEEDED ); }
Часто используемые и полезные функции:
Функция SetStDayTime() возвращает время начала торгового дня(на момент запроса).
Функция GetExgangeFee() возвращает комиссию биржи и кол-во сделок за торговый день (на момент запроса):
Ну прям беспрецендентный претендент на звание "Индусский Кодер - 2015".
SetStDayTime() решается двумя строчками. Но вам конечно не надо...
Михаил, благодарю за ваши функции!
Изобретение мною некоторых велосипедов отменяется )
Очень надо.
И как же?
Надо работать с числовым представлением времени.
datetime a=TimeTradeServer();
Время начала дня:
datetime r=(a/86400)*86400
Время в 19:00 сегодня:
datetime r=(a/86400)*86400+19*3600;
Если время в 19:00 сегодня больше текущего, значит нужны вчерашние 19:00:
if(r>a)r-=86400;
Тут, если надо пропустить выходные, проверяем день недели, если воскресенье, вычитаем 86400*2, если суббота, вычитаем 86400 (чтобы получить пятницу).
Как-то так.
Потом, для отображения, если надо, переводим в строку:
TimeToStr(r)
А высокосный год?
А теперь, воплотите Ваши мысли в конкретный код.
Перепешите мою функцию по своему, и как Вы говорили в ДВЕ строчки!
А что високосный год? Все будет нормально.
Воплотите сами, не хочу полностью разбираться с вашим кодом, вдруг что упущу, вот вам радости-то будет.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Добрый день!
Здесь буду выкладывать рекомендации, баги, особенности и часто используемые функции на срочном рынке ФОРТС
ВАЖНО: Чтобы не "растягивать" топик, при возникновении замечаний,
или есть вопросы - создать в этом разделе отдельную тему (здесь отвечать не буду).
Рекомендация:
Стандартная библиотека MQL5 "заточена" на рынок ФОРЕКС, поэтому для
разработки экспертов для ФОРТС рекомендую всё писать самим.
Часто используемые и полезные функции:
Функция проверки торговых параметров сервера брокера.
В этой функции необходимо проверять те параметры, которые
Вы будете использовать в своём советнике. Вот пример:
(использовать ТОЛЬКО в OnInit() )
Пример использования:
Получение количества дней, оставшихся до экспирации инструмента:
Получение "чистой" цены позиции, без учёта клирингов:
Создание глобальной переменной терминала для подсчёта транзакций:
( Использовать ТОЛЬКО в OnInit() )
Защищённая запись в глобальную переменную терминала ( счётчик транзакций ):
Если параметр up_down = true, то увеличиваем глобальную переменную терминала,
и наоборот.
Проверка денежных средств с автоматическим понижением объёма, при нехватке денег:
Установка рыночного / лимитного ордера командой OrderSend()
если price = ''0" - ордер рыночный:
Удаление ордера командой OrderSend()
Установка отложенного ордера командой OrderSend()
Модификация отложенного ордера командой OrderSend()
Установка отложенного ордера командой OrderSendAsync()
При использовании этой команды, билет получаем не в результате этой
функции, а в функции OnTradeTransaction(). В функции OrderSendAsync() мы
получаем номер запроса на установку ордера:
ulong order_ticket = 0;
Получение билета по номеру запроса:
Обработка ошибок ( кодов возврата) функций OrderSend() и OrderSendAsync()
в реализацию отправки ордера добавляется функция CheckError() Пример:
Сама функция CheckError() (в примере не все коды возврата)
См. продолжение
Особенности:
Покупая более ОДНОГО контракта ЛИМИТНЫМ ордером с исполнением ORDER_FILLING_IOC,
ордер в истории может храниться как ORDER_STATE_CANCELED, если ордер залился первым объёмом,
а вторым не успел.
Пример:
Покупая 3 контракта ЛИМИТНЫМ ордером с исполнением ORDER_FILLING_IOC,
складывается следующая ситуация:
1. Если мы купили все три контракта, то ордер в истории имеет состояние = ORDER_STATE_FILLED
2. Если мы ничего не купили, то в истории состояние = ORDER_STATE_CANCELED
3. Если мы купили первых два контракта (28449), а 1 контракт не купили (28450), то в истории состояние = ORDER_STATE_CANCELED
4. Если мы не купили первых два контракта (28449), а купили 1 (28450), то в истории состояние = ORDER_STATE_PARTIAL
======= Конец примера ===================
Количество не эффективных транзакций ( не эффективной транзакцией считается транзакция не приведшая к сделке.
Установка, модификация и удаление ордера) на срочном рынке ФОРТС ограничено 2000 за полную торговую сессию
с 19-00 текущего дня до 18-45 следующего дня. За превышение - штраф Биржи
http://moex.com/n8725
Баги:
1. Если на сервере МТ5 брокера или на бирже происходит сбой, то на команду
удалить(модифицировать) СУЩЕСТВУЮЩИЙ ордер сервер возвращает:
ошибку 10013 = TRADE_RETCODE_INVALID = Неправильный запрос ( Invalid request )
2. Иногда, тоже при сбое, при попытке установить отложенный или лимитный ордер, возникает ошибка - "Инструмент отсутствует в текуще"
(это не опечатка, а именно такое сообщение)
В документации какого кода возврата торгового сервера - нет!