Что Вы имеете ввиду на "планке"?
Стакан на ФОРТС агрегирован, т.е цены расположены сверху вниз от большего к меньшему (если смотреть на стакан в терминале).
Глубину стакана (сколько ask и bid) устанавливает брокер и в Открывашке и в БКС по не более 20 записей для ask и bid (максимально может быть по 50 записей QUIK).
В структуре MqlBookInfo[0] - располагается самый большой ask (при его наличии)
//+------------------------------------------------------------------+ //| Book_test.mq5 | //| Copyright 2020 prostotrader | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2020 prostotrader" #property link "https://www.mql5.com" #property version "1.00" bool is_book = false; MqlBookInfo book_price[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Add books is_book = MarketBookAdd(Symbol()); if(is_book = true) { Print(__FUNCTION__, ": Подписка на стакан добавлена. Символ ", Symbol()); } else { Print(__FUNCTION__, ": Подписка на стакан не добавлена. Символ ", Symbol()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(is_book = true) MarketBookRelease(Symbol()); Print(__FUNCTION__, ": Подписка на стакан удалена. Символ ", Symbol()); } //+------------------------------------------------------------------+ //| BookEvent function | //+------------------------------------------------------------------+ void OnBookEvent(const string &symbol) { if(symbol == Symbol()) //Проверка ОБЯЗАТЕЛЬНА! { if(MarketBookGet(Symbol(), book_price) == true)//getBook { int size = ArraySize(book_price); if(size > 0) { for(int i = 0; i < size; i++) { if(book_price[i].type == BOOK_TYPE_SELL) { //Get book sell data } else if(book_price[i].type == BOOK_TYPE_BUY) { //Get book buy data } } } } } } //+------------------------------------------------------------------+
Добавлено
Процедуру OnBookEvent() целесообразно использовать, если Вам необходимо получать не только лучший ask и bid
- www.mql5.com
Что Вы имеете ввиду на "планке"?
Стакан на ФОРТС агрегирован, т.е цены расположены сверху вниз от большего к меньшему (если смотреть на стакан в терминале).
Глубину стакана (сколько ask и bid) устанавливает брокер и в Открывашке и в БКС по не более 20 записей для ask и bid (максимально может быть по 50 записей QUIK).
В структуре MqlBookInfo[0] - располагается самый большой ask (при его наличии)
Добавлено
Процедуру OnBookEvent() целесообразно использовать, если Вам необходимо получать не только лучший ask и bid
Как устроен стакан я знаю.
Еще раз вопрос:
Что происходит в массиве из 40 элементов при отсутствии, например, предложения?
- Первые 20 элементов будут содержать нули?
- Первые 20 элементов будут содержать информацию о bid'ах?
- Весь массив будет состоять не из 40, а из 20 элементов, которые будут содержать только bid'ы?
Интересует только практический опыт. Как это должно быть теоретически я представляю, хочется подтверждений.
А нет-ли возможности получать не полный стакан, а только 3 аска и 3 бида, например. В документации я не нашёл, да и не очень старательно искал.
А зачем? Вы получаете целиком массив, а потом делаете с ним все, что захотите.
А зачем? Вы получаете целиком массив, а потом делаете с ним все, что захотите.
Как устроен стакан я знаю.
Еще раз вопрос:
Что происходит в массиве из 40 элементов при отсутствии, например, предложения?
- Первые 20 элементов будут содержать нули?
- Первые 20 элементов будут содержать информацию о bid'ах?
- Весь массив будет состоять не из 40, а из 20 элементов, которые будут содержать только bid'ы?
Интересует только практический опыт. Как это должно быть теоретически я представляю, хочется подтверждений.
Размер
int size = ArraySize(book_price);
показывает сколько записей в действительности в стакане.
А какие из них ask или bid показывает
if(book_price[i].type == BOOK_TYPE_SELL)
Если размер size = 0, то стакан пустой.
//+------------------------------------------------------------------+ //| Book_test.mq5 | //| Copyright 2020 prostotrader | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2020 prostotrader" #property link "https://www.mql5.com" #property version "1.00" // bool is_book = false; MqlBookInfo book_price[]; int cnt = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Add books is_book = MarketBookAdd(Symbol()); if(is_book = true) { Print(__FUNCTION__, ": Подписка на стакан добавлена. Символ ", Symbol()); } else { Print(__FUNCTION__, ": Подписка на стакан не добавлена. Символ ", Symbol()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(is_book = true) MarketBookRelease(Symbol()); Print(__FUNCTION__, ": Подписка на стакан удалена. Символ ", Symbol()); } //+------------------------------------------------------------------+ //| BookEvent function | //+------------------------------------------------------------------+ void OnBookEvent(const string &symbol) { if(symbol == Symbol()) { cnt++; if(cnt >=2) return; if(MarketBookGet(Symbol(), book_price) == true)//getBook { int size = ArraySize(book_price); if(size > 0) { for(int i = 0; i < size; i++) { if(book_price[i].type == BOOK_TYPE_SELL) { Print(__FUNCTION__, ": Получена запись Sell. Цена = ", book_price[i].price, "; Объем = ", book_price[i].volume); } else if(book_price[i].type == BOOK_TYPE_BUY) { Print(__FUNCTION__, ": Получена запись Buy. Цена = ", book_price[i].price, "; Объем = ", book_price[i].volume); } } } else Print(__FUNCTION__, ": Стакан ", Symbol(), " пустой!"); } if(MarketBookGet("UCAD-9.20", book_price) == true)//getBook { int size = ArraySize(book_price); if(size > 0) { for(int i = 0; i < size; i++) { if(book_price[i].type == BOOK_TYPE_SELL) { Print(__FUNCTION__, ": Получена запись Sell. Цена = ", book_price[i].price, "; Объем = ", book_price[i].volume); } else if(book_price[i].type == BOOK_TYPE_BUY) { Print(__FUNCTION__, ": Получена запись Buy. Цена = ", book_price[i].price, "; Объем = ", book_price[i].volume); } } } else Print(__FUNCTION__, ": Стакан UCAD-9.20 пустой!"); } } } //+------------------------------------------------------------------+
2020.05.14 16:33:05.542 Book_test (UCAD-6.20,M1) OnInit: Подписка на стакан добавлена. Символ UCAD-6.20 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Sell. Цена = 1.412; Объем = 2000 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Sell. Цена = 1.4119; Объем = 1000 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Sell. Цена = 1.4118; Объем = 2500 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Sell. Цена = 1.4116; Объем = 625 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Buy. Цена = 1.4109; Объем = 625 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Buy. Цена = 1.4108; Объем = 1000 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Buy. Цена = 1.4107; Объем = 1000 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Получена запись Buy. Цена = 1.4106; Объем = 1000 2020.05.14 16:33:05.656 Book_test (UCAD-6.20,M1) OnBookEvent: Стакан UCAD-9.20 пустой! 2020.05.14 16:33:13.221 Book_test (UCAD-6.20,M1) OnDeinit: Подписка на стакан удалена. Символ UCAD-6.20
А нет-ли возможности получать не полный стакан, а только 3 аска и 3 бида, например. В документации я не нашёл, да и не очень старательно искал.
//+------------------------------------------------------------------+ //| Book_test.mq5 | //| Copyright 2020 prostotrader | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2020 prostotrader" #property link "https://www.mql5.com" #property version "1.00" // #define sell_records 3 #define buy_records 3 struct BOOK_DATA { int total_cnt; int sell_cnt; int buy_cnt; int sell_pos; int buy_pos; MqlBookInfo b_data[]; bool is_first; }; bool is_book = false; BOOK_DATA book_data; int cnt = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Add books is_book = MarketBookAdd(Symbol()); if(is_book == true) { Print(__FUNCTION__, ": Book added. Symbol = ", Symbol()); } else { Print(__FUNCTION__, ": No book added. Symbol = ", Symbol()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(is_book == true) { MarketBookRelease(Symbol()); Print(__FUNCTION__, ": Book removed. Symbol = ", Symbol()); } } //+------------------------------------------------------------------+ //| BookEvent function | //+------------------------------------------------------------------+ void OnBookEvent(const string &symbol) { if(symbol == Symbol()) { cnt++; if(cnt >=2) return; if(MarketBookGet(Symbol(), book_data.b_data) == true) { book_data.sell_cnt = 0; book_data.buy_cnt = 0; book_data.total_cnt = ArraySize(book_data.b_data); if(book_data.total_cnt > 0) { book_data.is_first = true; for(int i = 0; i < book_data.total_cnt; i++) { if(book_data.b_data[i].type == BOOK_TYPE_SELL) { book_data.sell_cnt++; } else if(book_data.b_data[i].type == BOOK_TYPE_BUY) { book_data.buy_cnt++; if(book_data.is_first == true) { book_data.is_first = false; if(book_data.sell_cnt > 0) { book_data.sell_pos = i-1; } else book_data.sell_pos = -1; } if(book_data.buy_cnt == buy_records) { book_data.buy_pos = i; break; } } } //--- Print data --- Print(__FUNCTION__, ": Total records = ", book_data.total_cnt); Print(__FUNCTION__, ": Sell records = ", book_data.sell_cnt); Print(__FUNCTION__, ": Buy records = ", book_data.total_cnt - book_data.sell_cnt); if((book_data.buy_cnt == buy_records) && (book_data.sell_cnt >= sell_records)) { for(int i = book_data.sell_pos + sell_records - 1; i >= book_data.sell_pos; i--) { Print(__FUNCTION__, ": Sell record. Price = ", book_data.b_data[i].price, " Volume = ", book_data.b_data[i].volume); } for(int i = book_data.buy_pos; i < (book_data.buy_pos + buy_records); i++) { Print(__FUNCTION__, ": Buy record. Price = ", book_data.b_data[i].price, " Volume = ", book_data.b_data[i].volume); } } else Print(__FUNCTION__, ": Invalid records range!"); } else Print(__FUNCTION__, ": Book is enpty. Symbol = ", Symbol()); } else Print(__FUNCTION__, ": Get book failed. Symbol = ", Symbol()); } } //+------------------------------------------------------------------+
2020.05.14 17:20:34.316 Book_test (GOLD-6.20,M1) OnInit: Подписка на стакан добавлена. Символ GOLD-6.20 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Total records = 40 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Sell records = 20 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Buy records = 20 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Sell record. Price = 1737.2 Volume = 500 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Sell record. Price = 1737.0 Volume = 9 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Sell record. Price = 1736.4 Volume = 2 //Best ask 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Buy record. Price = 1736.0 Volume = 4 //Best bid 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Buy record. Price = 1735.9 Volume = 25 2020.05.14 17:20:34.426 Book_test (GOLD-6.20,M1) OnBookEvent: Buy record. Price = 1735.8 Volume = 2 2020.05.14 17:20:38.023 Book_test (GOLD-6.20,M1) OnDeinit: Подписка на стакан удалена. Символ GOLD-6.20
Добавлено
Немного изменил код, чтобы меньше памяти юзалось и быстрее работало.
Размер
показывает сколько записей в действительности в стакане.
А какие из них ask или bid показывает
Если размер size = 0, то стакан пустой.
Спасибо, все логично.
Спасибо, я примерно так и сделал.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
ФОРТС структура стакана цен на "планке"
Alexey Viktorov, 2020.05.14 08:23
Это понятно, но если мне не надо больше 3х, то и копировать их нет необходимости. Разве не так? Не найдя возможности я так и поступил, получил сколько дали и вытащил то что интересует...- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Коллеги,
как выглядит массив стакана цен на "планке"? У кого то есть практический опыт?