Каким должен быть стакан цен? - страница 12

 
Задержка с выпуском стакана возникла из за того, что необходимо сделать новый тип движка. Стакан - как самостоятельное приложение, работающее как независимый движок, должно предоставлять пользовательский API, иначе, в качестве закрытой программы, его ценность будет гораздо меньше. Движки которые я делал ранее, были полностью зависимы от user-комманд и не имели собственного функционала. Новый тип движка, должен работать как самостоятельно, так и под управлением со стороны. Сейчас решаю эту задачу.
 

Cегодняшний день ознаменовался еще одним важным шагом вперед. Теперь движок может работать как самостоятельное приложение, синхронизируя значения своих параметров с подключенным к нему польз.приложением. Приложение, подключается как и раньше, но теперь оно может затребовать значения, которые устанавливаются функционалом движка. Таким образом, это переход на новый уровень взаимодействия программ.  Движок, как самостоятельное программа может накапливать свой функционал и расширять предоставляемый приложениям API. 

В случае со стаканом цен, - он стал самостоятельным приложением (которое я завтра-послезавтра закончу), и работает как индикатор. Используя подключение, пользователи могут получать значения этого стакана и переопределять их, возвращая их в стакан в измененном виде. Например: Цена в одном из полей стакана была проанализирована пользовательским кодом и оказалось, что это уровень некого важного индикатора. Пользователь посылает в то поле свой строковый маркер и он появится рядом с той ценой. Это открывает новые интересные возможности развития как движков, так и пользовательских программ.

ЗЫ. События GUI движков, ранее только посылавшиеся приложению, теперь поступают также во внутренний функционал движка и осуществляется параллельная обработка событий сразу на двух концах - в движке (в соответствии с заложенным моим кодом) и пользоват. приложением (в соответствии с пользовательским кодом). Нажали на кнопку - сработает и функционал движка, и функционал подключенного приложения.
 
Ещё такой фишке в стакане не хватает, как прибыль, если закрыться сейчас по рынку, т.е. учет наполнения стакана - актуально для позиций чуть больше маленьких (к примеру 100-150 лотов).
 
Горячие клавиши будут?
 
Andrey Gladyshev:
Горячие клавиши будут?
Обязательно.
 
Aleksey Vyazmikin:
Ещё такой фишке в стакане не хватает, как прибыль, если закрыться сейчас по рынку, т.е. учет наполнения стакана - актуально для позиций чуть больше маленьких (к примеру 100-150 лотов).
Учёт наполнения стакана. Подумаю после выпуска базовой версии, чтобы не затягивать.
 
Стакан цен будет готов. Сильно задержала документация подключения АPI. Чрезвычайно трудоёмкое дело писать свою документацию на своем языке разметки. И документацию стакана тоже нужно делать. И сам стакан. И параллельно оптимизировать код, конструктор, исправлять баги, добавлять возможности. Поэтому так долго. Но потом все будет быстрее и быстрее.
 
На каком языке пишется программа?
Какая фактическая скорость обработки входящих данных?
Как распределяются данные по уровням цен?
В цикле for или по каждому уровню своя переменная с данными?
То что выбрали тип отображения стакана на подобие западных терминалов, это правильно.
Я бы предложил добавить в стакан, управление связанными заявками OCO до трёх уровней.
А вообще можно взять любой функциональный западный стакан и посмотреть что в них реализовано.
Или посмотреть как реализован скальперский привод QScalp.
 
Roman:
На каком языке пишется программа?
Какая фактическая скорость обработки входящих данных?
Как распределяются данные по уровням цен?
В цикле for или по каждому уровню своя переменная с данными?
То что выбрали тип отображения стакана на подобие западных терминалов, это правильно.
Я бы предложил добавить в стакан, управление связанными заявками OCO до трёх уровней.

1. Программа пишется на двух языках. Базовый язык MQL5, и поверх него, мой язык разметки. 

2. Распределяются также, как присылаются. В смысле, в нужные ячейки. Словами сложно обьяснить. Позже скину код. Конечно, там пришлось попотеть, чтобы данные попадали в нужные ячейки, но этот вопрос решен.

3. Да, буду добавлять всё что попросят и что имеет смысл и важность.
 

Вот код распределения данных по ячейкам моего стакана:

void On_DOM_Event()
{
 int t = 0;
 //----------------------------
 MqlTick last_tick;
 SymbolInfoTick(Symbol(),last_tick);
 //----------------------------
 MarketBookGet(NULL,priceArray); 
 //----------------------------
 double p = 0;
 long   ask_size = 0, bid_size = 0;
 int    s = ArraySize(priceArray);
 //----------------------------
 if(s > 0)
   {
    //-------------------------   ---
    for(int i1 = 0; i1 < 100; i1++)prices[i1]  = NULL;
    for(int i1 = 0; i1 < 100; i1++)ask_vol[i1] = NULL;
    for(int i1 = 0; i1 < 100; i1++)bid_vol[i1] = NULL; 
    //----------------------------
    int Closest_to_ask = 0;
    //----------------------------
    for(int a1 = 0; a1 < s; a1++)
      {
       if(
              priceArray[a1].price == last_tick.ask
          || (priceArray[a1].price < last_tick.ask && (((a1 + 1 < s) && priceArray[a1 + 1].price >= last_tick.bid) || (a1 + 1 == s)))
         )
         {
          Closest_to_ask = a1;
          break;
         } 
      } 
    //----------------------------
    for(int a2 = Closest_to_ask; a2 >= 0; a2--)
      { //Alert("t ",t,"  a2  ",a2);
       prices[49-t]  =  Normalize_Double(priceArray[a2].price,_Digits,_Point);
       ask_size     +=  priceArray[a2].volume;
       ask_vol[49-t] =  (string)priceArray[a2].volume;
       t++;
      }
    //--------------------------------  
    t = 0;
    //Alert("_Digits   ",_Digits);
    //--------------------------------  
    for(int a3 = Closest_to_ask + 1; a3 < s; a3++)
      { 
       prices[50+t]  =   Normalize_Double(priceArray[a3].price,_Digits,_Point);
       bid_size      +=  priceArray[a3].volume;
       bid_vol[50+t] =   (string)priceArray[a3].volume;
       t++;
      }         
 //------------------------------------------------       
 //------------------------------------------------ 
 E_DOM_1_Price(prices[40]);    E_DOM_1_Ask_size(ask_vol[40]);
 E_DOM_2_Price(prices[41]);    E_DOM_2_Ask_size(ask_vol[41]); 
 E_DOM_3_Price(prices[42]);    E_DOM_3_Ask_size(ask_vol[42]); 
 E_DOM_4_Price(prices[43]);    E_DOM_4_Ask_size(ask_vol[43]); 
 E_DOM_5_Price(prices[44]);    E_DOM_5_Ask_size(ask_vol[44]);
 E_DOM_6_Price(prices[45]);    E_DOM_6_Ask_size(ask_vol[45]);
 E_DOM_7_Price(prices[46]);    E_DOM_7_Ask_size(ask_vol[46]);
 E_DOM_8_Price(prices[47]);    E_DOM_8_Ask_size(ask_vol[47]);  
 E_DOM_9_Price(prices[48]);    E_DOM_9_Ask_size(ask_vol[48]); 
 E_DOM_10_Price(prices[49]);   E_DOM_10_Ask_size(ask_vol[49]);
 //-------------------------------------------------
 E_DOM_11_Price(prices[50]);  E_DOM_11_Bid_size(bid_vol[50]);
 E_DOM_12_Price(prices[51]);  E_DOM_12_Bid_size(bid_vol[51]);
 E_DOM_13_Price(prices[52]);  E_DOM_13_Bid_size(bid_vol[52]); 
 E_DOM_14_Price(prices[53]);  E_DOM_14_Bid_size(bid_vol[53]); 
 E_DOM_15_Price(prices[54]);  E_DOM_15_Bid_size(bid_vol[54]); 
 E_DOM_16_Price(prices[55]);  E_DOM_16_Bid_size(bid_vol[55]); 
 E_DOM_17_Price(prices[56]);  E_DOM_17_Bid_size(bid_vol[56]); 
 E_DOM_18_Price(prices[57]);  E_DOM_18_Bid_size(bid_vol[57]);    
 E_DOM_19_Price(prices[58]);  E_DOM_19_Bid_size(bid_vol[58]); 
 E_DOM_20_Price(prices[59]);  E_DOM_20_Bid_size(bid_vol[59]);
 //------------------------------------------------- 
 }
 RMSG(1);
}


Для записи приходящих данных сделал массив в 100 ячеек. Приходящие данные расфасовываю от его центра (ячейка 49) в сторону аск и бид, предварительно вычисляя наиближайшую цену к аск и к бид. 

Причина обращения: