Здравствуйте,
Я давно разрабатываю роботы на MQL5. Хочу перенести часть своих робов на КВИК. Я вообще не люблю эту платформу и никогда для неё не писал. С чего начать обучение? Есть ли тут профессионалы, которые программируют и для КВИКА и занимался переводом экспертов из mql в КВИК?
Бросьте эту затею, потому что даже если что-то напишите на QLUA, оттестировать не сможете.
Единственный выход - вывод данных через DDE сервер и транзакции через trans2quik.dll
Здравствуйте,
Я давно разрабатываю роботы на MQL5. Хочу перенести часть своих робов на КВИК. Я вообще не люблю эту платформу и никогда для неё не писал. С чего начать обучение? Есть ли тут профессионалы, которые программируют и для КВИКА и занимался переводом экспертов из mql в КВИК?
Alexey Volchanskiy, Stanislav Dray
Вы все-равно будете писать СВОЁ приложение, человеку не нужно связывать МТ5 с КВИК.
Поэтому самый лучший вариант, это как я описал выше.
Пишем DDE сервер, туда же "цепляем" trans2quik.dll и робот(ы) готов.
unit DdeExlUnt; interface uses Winapi.Windows, System.Classes, System.Types, Vcl.Forms, Winapi.DdeMl, System.SysUtils, System.StrUtils, Vcl.Controls, Winapi.Messages, QTypes; const WM_DDE_ADDQUE = WM_USER + 2; var ServiceName: string;// = 'quikdde'; // DDE server name procedure ClearTable(Table: TVariantTable); overload; type TPokeAction = (paAccept, paPass, paReject); TDdePokeEvent = procedure(const Topic: string; var Action: TPokeAction) of object; TDdeDataEvent = procedure(const Topic: string; Cells: TRect; Data: TVariantTable) of object; PDdeQueItem = ^TDdeQueItem; TDdeQueItem = packed record data: Pointer; size: integer; sTopic: String; sCells: String; end; TDdeServer = class(TWinControl) private Inst: Integer; ServiceHSz: HSz; TopicHSz: HSz; fOnPoke: TDdePokeEvent; fOnData: TDdeDataEvent; fDdeQue: TThreadList; protected function XLTDecodeV(data: pointer; datasize: integer): TVariantTable; function DecodeCellAddr(CellAddr: string): TRect; procedure AddQue(var Message: TWMSysCommand); message WM_DDE_ADDQUE; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published property OnPoke: TDdePokeEvent read fOnPoke write fOnPoke; property OnData: TDdeDataEvent read fOnData write fOnData; end; {var DdeServer: TDdeServer;} //--- Pointer functions ---- function addp(p: Pointer; increment: int64 = 1): Pointer; overload; function addp(p: Pointer; increment: pointer): Pointer; overload; function subp(p: Pointer; decrement: int64 = 1): Pointer; overload; function subp(p: Pointer; decrement: pointer): Pointer; overload; implementation uses main; function CallbackProc(CallType, Fmt: UINT; Conv: HConv; hsz1, hsz2: HSZ; Data: HDDEData; Data1, Data2: DWORD): HDDEData stdcall; var action: TPokeAction; sTopic: String; P: PDdeQueItem; Buff: array[0..255] of WideChar; begin result:= DDE_FNOTPROCESSED; //--- case CallType of XTYP_CONNECT: result:= 1; XTYP_POKE: begin DdeQueryString(QTrader.DdeServer.Inst, HSz1, @Buff, sizeof(Buff), CP_WINUNICODE); sTopic:= string(Buff); action:= paPass; if Assigned(QTrader.DdeServer.fOnPoke) then QTrader.DdeServer.fOnPoke(sTopic, action); //--- case action of paAccept: begin DdeQueryString(QTrader.DdeServer.Inst, HSz2, @Buff, sizeof(Buff), CP_WINUNICODE); New(P); P^.sTopic:= sTopic; P^.sCells:= string(Buff); P^.size:= DdeGetData(Data, nil, 0, 0); GetMem(P^.data, P^.size); DdeGetData(Data, P^.data, P^.size, 0); //--- with QTrader.DdeServer.fDdeQue.LockList do try add(P); finally QTrader.DdeServer.fDdeQue.UnlockList; end; if (QTrader.DdeServer.Handle <> 0) then PostMessage(QTrader.DdeServer.Handle, WM_DDE_ADDQUE, 0, 0); result:= DDE_FACK; end; paPass: result:= DDE_FACK; paReject: result:= DDE_FNOTPROCESSED; end; end; end; end; constructor TDdeServer.Create; begin inherited; fDdeQue := TThreadList.Create; Parent := TWinControl(AOwner); CreateHandle; Inst := 0; if (DdeInitialize(Inst, @CallbackProc, APPCLASS_STANDARD, 0) = DMLERR_NO_ERROR) then begin ServiceHSz := DdeCreateStringHandle(Inst, PWideChar( ServiceName ), CP_WINUNICODE); if ( DdeNameService(Inst, ServiceHSz, 0, DNS_REGISTER) = 0 ) then raise Exception.Create( 'Не удалось зарегистрировать имя DDE-сервиса ''' + ServiceName + '''' ); TopicHSz := DdeCreateStringHandle(Inst, PWideChar('Topic'), cp_WinUnicode); end else raise Exception.Create( 'Не удалось выполнить инициализацию DDE' ); end; destructor TDdeServer.Destroy; begin DdeNameService(Inst, ServiceHsz, 0, DNS_UNREGISTER); fDdeQue.Free; DdeFreeStringHandle(Inst, ServiceHsz); DdeUninitialize(Inst); inherited; end; procedure TDdeServer.AddQue(var Message: TWMSysCommand); var vt: TVariantTable; Cells: TRect; p: PDdeQueItem; i: integer; begin with fDdeQue.LockList do try p:= PDdeQueItem(Items[Count - 1]); Cells:= DecodeCellAddr(p^.sCells); vt:= XLTDecodeV(p^.data, p^.size); if Assigned(QTrader.DdeServer.fOnData) then QTrader.DdeServer.fOnData(p^.sTopic, Cells, vt); for i:= (Count - 1) downto 0 do begin p:= Items[i]; FreeMem(p^.data, p^.size); Delete(i); Dispose(p); end; finally fDdeQue.UnlockList; end; end; function TDdeServer.XLTDecodeV(data: pointer; datasize: integer): TVariantTable; var i: integer; curr: pointer; BlockType: word; BlockSize: word; StringSize: byte; RealData: real; StringData: shortstring; DataNum: integer; begin curr:= addp(data, 4); result.RowCount := Word(curr^); curr:= addp(curr, 2); result.ColCount := Word(curr^); curr:= addp(curr, 2); //--- set array size --- SetLength(result.Cells, result.RowCount); //--- for i := 0 to result.RowCount - 1 do SetLength(result.Cells[i], result.ColCount); //--- data block -------- DataNum := 0; while (Integer(subp(curr, data)) < datasize) do begin BlockType:= Word(curr^); curr:= addp(curr, 2); BlockSize:= Word( curr^ ); curr:= addp( curr, 2 ); case BlockType of 1: begin while(BlockSize > 0) do begin RealData:= Real(curr^); curr:= addp(curr, 8); dec(BlockSize, 8); result.Cells[(DataNum div result.ColCount), (Datanum mod result.ColCount)]:= RealData; inc(DataNum); end; end; 2: begin while(BlockSize > 0) do begin StringSize:= Byte(curr^); curr:= addp( curr ); StringData[0]:= AnsiChar(Chr(StringSize)); //--- for i:= 1 to StringSize do begin StringData[i]:= AnsiChar(Char(curr^)); curr:= addp(curr); end; result.Cells[(DataNum div result.ColCount), (Datanum mod result.ColCount)]:= StringData; inc(DataNum); dec(BlockSize, StringSize + 1); end; end; end; end; end; function TDdeServer.DecodeCellAddr( CellAddr: string ): TRect; var tmp1, tmp2: integer; begin CellAddr:= UpperCase(CellAddr); tmp1:= PosEx('R', CellAddr); tmp2:= PosEx('C', CellAddr, tmp1); try result.Top:= StrToInt(copy(CellAddr, tmp1 + 1, tmp2 - tmp1 - 1)) - 1; except exit; end; tmp1:= PosEx('R', CellAddr, tmp2); try Result.Left:= StrToInt(copy(CellAddr, tmp2 + 1, tmp1 - tmp2 - 1 - 1)) - 1; except exit; end; tmp2:= PosEx('C', CellAddr, tmp1); try result.Bottom:= StrToInt(copy(CellAddr, tmp1 + 1, tmp2 - tmp1 - 1)) - 1; result.Right:= StrToInt(copy(CellAddr, tmp2 + 1, Length(CellAddr) - tmp2)) - 1; except exit; end; end; procedure ClearTable(Table: TVariantTable); begin SetLength(Table.Cells, 0); Table.RowCount:= 0; Table.ColCount:= 0; end; function addp(P: Pointer; increment: int64 = 1): Pointer; overload; begin result:= Pointer(Int64(p) + increment); end; function addp(P: Pointer; increment: Pointer): Pointer; overload; begin result:= Pointer(Int64(p) + Int64(increment)); end; function subp(P: Pointer; decrement: int64 = 1): Pointer; overload; begin result:= Pointer(Int64(p) - decrement); end; function subp(P: Pointer; decrement: Pointer): Pointer; overload; begin result:= Pointer(Int64(p) - Int64(decrement)); end; end.
Alexey Volchanskiy, Stanislav Dray
Вы все-равно будете писать СВОЁ приложение, человеку не нужно связывать МТ5 с КВИК.
Поэтому самый лучший вариант, это как я описал выше.
Пишем DDE сервер, туда же "цепляем" trans2quik.dll и робот(ы) готов.
круть, лет 15 Дельфю не щупал ))
круть, лет 15 Дельфю не щупал ))
Леш, да какая разница на чем писать?
Просто XE4 у меня лицензионная и 64-битная.
Досталась по случаю.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Здравствуйте,
Я давно разрабатываю роботы на MQL5. Хочу перенести часть своих робов на КВИК. Я вообще не люблю эту платформу и никогда для неё не писал. С чего начать обучение? Есть ли тут профессионалы, которые программируют и для КВИКА и занимался переводом экспертов из mql в КВИК?