Нужна помощь профессионального программиста - страница 19

 
Из описания API и из примеров, не понятно для каждого потока используется свой лисенер или один?
 
prostotrader #:
Из описания API и из примеров, не понятно для каждого потока используется свой лисенер или один?

В общем, Дмитрий, я разобрался.

1. Для получения потоков репликации нужно создавать соединение, а в этом соединении

создавать столько лисенеров, сколько Вы будите слушать потоков.

Но колбэк может быть один, чтобы различать потоки,  при создании лисенера в Data мы можем записывать сой идентификатор 

cg_lsn_new_t = function(Conn: pcg_conn_t; const settings: PAnsiChar; cb: cg_listener_cb_t; data: Pointer; var hLsn: pcg_listener_t): CG_RESULT; stdcall;

Который мы получим в колбэеке

typedef CG_RESULT (CG_API *CG_LISTENER_CB)(cg_conn_t* conn, cg_listener_t* listener, struct cg_msg_t* msg, void* data);

(даже можно создать структуру, по которой будут обрабатываться данные из сообщения)

2. Для отправки сообщений, нужно создать другое соединение, в котором должен быть как паблишер, так и лисенер.

Я решил, что для каждого робота будет создаваться свое соединение с паблишером и лисенером.

Вот как-то так

 

Ок, спасибо за инфу!

В шарпе то там поудобней сделано, в самом языке. Там через, так называемые, делегаты. Без прямых колбэков.

 
Dmitriy Skub #:

Ок, спасибо за инфу!

В шарпе то там поудобней сделано, в самом языке. Там через, так называемые, делегаты. Без прямых колбэков.

Понятно. Как Вы планируете организовать хранение данных?

И вообще, какую задачу Вы ставите перед собой?

Я, например, хочу написать коннектор, который мог бы торговать и фьючерсами и опционами,

при этом чтобы работал не один робот, а несколько, а какая задача у Вас?

 

Дошел до получения сообщений

Теперь, нужно серьезно думать о "складировании" информации...

 
prostotrader #:

Дошел до получения сообщений

Теперь, нужно серьезно думать о "складировании" информации...

А какую информацию собираетесь складировать? Тики (в широком смысле), что ли? И за какой период?
 
Dmitriy Skub #:
А какую информацию собираетесь складировать? Тики (в широком смысле), что ли? И за какой период?

Как какую? Текущую (история не нужна для роботов)

Инструменты, параметры инструментов, параметры сессии текущие средства, в общем все то, что

нужно для торговли 

 
prostotrader #:

Как какую? Текущую (история не нужна для роботов)

Инструменты, параметры инструментов, параметры сессии текущие средства, в общем все то, что

нужно для торговли 

Это называется торговое окружение. Дык, для полностью своей проги проблем нет - что структурировано (символы), то в коллекцию.

Что не структурировано, то в отдельные структуры. Просто, чтобы потом править проще было. Я, вообще, ООП использую.

У меня начальная задача - повторить то, что для мт5 сделано. Для этого нужен приемник данных с биржи и транслятор торговых приказов (то, что коннектором зовут).

Коннектор будет к серверу данных подключаться, а из него уже будет раздача/прием на/с верхний уровень - терминалы, роботы и т.д. Так более гибко получается.

Ну и генератор сигналов в каком-то виде простейшем по текущей стратегии. Потом уже можно дальше это направление развивать. Есть еще несколько проектов связанных.

По опционам - там ликвидность почти нулевая - только центральные страйки более-менее. Для стратегий нужно дельта-хэджер автоматический делать и т.д. много еще чего.

Есть идея эмулировать опционы фьючерсами, даже есть написанные классы. Соответственно, можно городить конструкции на фьючах.

 
Не получается "засунуть" все лисенеры в один колбэк, - крешится память, где инициализированы лисенеры
 
prostotrader #:
Не получается "засунуть" все лисенеры в один колбэк, - крешится память, где инициализированы лисенеры

Решил проблему, оказалось, что в классе, где происходит жизненный цикл объектов, нельзя

объявлять переменные

//--- Cgate connector ---
  TCGConnector = class(TThread)
      cgSettings: TConnectorSettings;                     // connector settings
      cgStorage: TStorage;                                // storage class
      cgEnv: boolean;                                     // Enviroiment
      cghConn: pcg_conn_t;                                // Connection
      cgLsns: TListeners;                                 // Listeners
    private
      procedure UpdMemo();                                       //
    protected
      procedure Execute; override;
      function MakeCallBack(const aConn: pcg_conn_t; const Param: string; var aListener: pcg_listener_t; Data: Pointer): CG_RESULT;
      function MsgCallBack(aConn: pcg_conn_t; hListn: pcg_listener_t; msg: pcg_msg_t; Data: Pointer): CG_RESULT; stdcall;
     public
       constructor Create(const val: boolean);
       destructor Destroy(); override;
       function GetCGRouterPath(const regKey: string; const RegValue: string): string;
       function GetCgService(const Machine: PWideChar; const sName: PWideChar): boolean;
       function LoadRouter(const FileName: string; const RKey: string;
                          const Rrec: string; const IniName: string;
                          const Machine: string; const ServName: string): Boolean;
  end;

Так как колбэк использует дату класса

//--- Call back ---
function P2LsnCallBack(aConn: pcg_conn_t; hList: pcg_listener_t; msg: pcg_msg_t; Data: Pointer): CG_RESULT; stdcall;
begin
  Result:= TCGConnector(Data).MsgCallBack(aConn, hList, msg, Data);
end;

Просто вынес переменные из класса и все заработало

Не совсем разобрался с CG_MSG_P2REPL_CLEARDELETED

и думаю, как лучше организовать хранение с быстрым доступом к данным

//--- Msg Call Back ---
function TCGConnector.MsgCallBack(aConn: pcg_conn_t; hListn: pcg_listener_t; msg: pcg_msg_t; Data: Pointer): CG_RESULT;
var
  eData: TExtData;
  LifeData: cg_data_lifenum_t;
begin
//--- Get stream name and position ---
  eData:= TExtData(Data^);
//--- Prosecc messages ---
  case msg.msg_type of
    CG_MSG_OPEN: cgLsns[eData.Pos].LsnParams.cgMsgOpen:= true;                  //Вызов lsn_close, conn_close из callback lsn допускается после получения сообщения CG_MSG_OPEN.
    CG_MSG_CLOSE: cgLsns[eData.Pos].LsnParams.cgMsgClose:= integer(Data^);      // Причина закрытия
    CG_MSG_TN_BEGIN: {curently not used};
    CG_MSG_TN_COMMIT: {curently not used};
    CG_MSG_STREAM_DATA: begin
      // TODO STORAGE!!!!!!!!!!!!!!!!! ?????????????????????????????
    end;
    CG_MSG_P2REPL_ONLINE: cgLsns[eData.Pos].LsnParams.cgMsgRplOnline:= true;
    CG_MSG_P2REPL_LIFENUM: begin
      LifeData:= cg_data_lifenum_t(msg^.data);
      cgLsns[eData.Pos].LsnParams.LifeNum:= LifeData.life_number;               // life number
      cgLsns[eData.Pos].LsnParams.LNFlags:= LifeData.flags;                     // life flags
    end;
    CG_MSG_P2REPL_CLEARDELETED: ;//TODO ????????????????????????????
    CG_MSG_P2REPL_REPLSTATE: cgLsns[eData.Pos].LsnParams.ReplState:= msg.data;  // store stream state
  end;
//--- result ---
  result:= CG_ERR_OK;
end;

Добавлено

Кстати, насчет Вашей идеи сделать нечто подобное МТ5.

Не тратьте зря время, одному очень сложно и долго писать подобный терминал,

наша задача ведь зарабатывать деньги... :)

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