Есть ли возможность получать котировки поступающие из Quik в свою программу, написанную например на С++ ?

 

Может быть кто то уже получал котировки как data feed из квика? Есть ли возможность получать по DDE или по ODBC?

Если кто то это уже делал это то приведите пример кода как это сделать плиз?

 
Вот здесь DLL для Quik и не только... кажется то о чем Вы спрашивали. И там еще парочку веток есть по Quik. Удачи.
 
elritmo >>:

Может быть кто то уже получал котировки как data feed из квика? Есть ли возможность получать по DDE или по ODBC?

Если кто то это уже делал это то приведите пример кода как это сделать плиз?

Где то я видел по автоматизации  QUICK инфу, поищите, есть такая инфа , GOOGLE Вам в помощь!

 
AAB писал(а) >>
Вот здесь DLL для Quik и не только... кажется то о чем Вы спрашивали. И там еще парочку веток есть по Quik. Удачи.

Спасибо за ссылку. Беглый взгляд на ветку на том форуме показал что там используют сложный механизм инжектирования длл в работающий процесс. Вообщем посмотрю.

Может кто ещё что подскажет как получать котировки.

 

ну как? получилось? стоит пробовать через хуки или есть способ получше?

 
Можно по ODBC получать любые данные из QUIK, а заявки отправлять через dll. Метод верный, неоднократно испробованный :)
 
Ну а можно просто прикинуться EXCEL ем для получения котировок от квика по DDE напрямую.
Единственная проблема, я не смог запустить эксель, если запущена моя прога. Видимо он ищет приложение с зарегистрированным
DDE сервером с именем EXCEL и если находит, то не запускается. Может кто подскажет как этого избежать.
Может надо выключить опцию DDE в экселе и выйти из него,
а потом снова запустить уже когда зупущена своя прога. Пока с этим не разбирался.

Вот часть кода чтобы понять как прикинуться DDE эксел сервером и извлекать котировки из буфера.
В квике надо настроить таблицу с нужными инструментами их именем и значением котировки Last Quote
Если потребуются другие данные с квика то придётся пошагово разбирать буфер приходящий от квика или найти его формат где-нибудь.
Может даже кто знает и подскажет в этой ветке. А так получаем самое важное имя инструмента и последнюю котировку по нему как
в таблице в квике они меняются.

DWORD Inst = 0;
HCONV Conv = 0;
HSZ ServiceHSz, TopicHSz;
char* DdeBuf = 0;


void DDEInit() {
    if(DdeInitialize(&Inst, (PFNCALLBACK)DdeCallback, APPCLASS_STANDARD, 0)!= DMLERR_NO_ERROR)
        return;
    ServiceHSz = DdeCreateStringHandle(Inst, "EXCEL", CP_WINANSI);
    TopicHSz = DdeCreateStringHandle(Inst, "[Книга1]Лист1", CP_WINANSI);
    if(DdeNameService(Inst, ServiceHSz, 0, DNS_REGISTER) == 0) {
	DDERelease();
    }
}

void DDERelease() {
    DdeNameService(Inst, ServiceHSz, 0, DNS_UNREGISTER);
    DdeFreeStringHandle(Inst, ServiceHSz);
    DdeFreeStringHandle(Inst, TopicHSz);
    DdeUninitialize(Inst);
}


HDDEDATA CALLBACK DdeCallback(UINT Type, UINT Fmt, HCONV Conv, HSZ Sz1, HSZ Sz2,
							  HDDEDATA Data, DWORD Data1, DWORD Data2) {
    if(Type == XTYP_CONNECT)
        return (HDDEDATA)1;
    else if(Type == XTYP_POKE) {
	   DdeQueryString(Inst, Sz1, StrBuf, sizeof(StrBuf), CP_WINANSI);
	   DdeQueryString(Inst, Sz2, StrBuf, sizeof(StrBuf), CP_WINANSI);
	   unsigned DdeBufSize = DdeGetData(Data, 0, sizeof(unsigned), 0);
	   if(DdeBufSize <= 0)
	      return (HDDEDATA)DDE_FACK;
	   if(!DdeBuf || (int)_msize(DdeBuf) < DdeBufSize)
	      DdeBuf = (char*)realloc(DdeBuf, DdeBufSize);
	   DdeGetData(Data, (LPBYTE)DdeBuf, DdeBufSize, 0);
	   DecodeQuikDDEBuffer(DdeBuf, DdeBufSize);
	   for(int i = 0; i < InstCnt; i++) {
	      if(Instrums[i].Instrums[i].QuoteValue == 0)
                continue;
           //Что нибудь делаем с новой котировкой по i инструменту 
           Instrums[i].QuoteValue;
        }
        return (HDDEDATA)DDE_FACK;
    }
    return (HDDEDATA)0;
}

void DecodeQuikDDEBuffer(char* Buf, int BufSize) {
    int BlockType = 0;
    int StringSize = 0;
    double RealData = 0;
    char StringData[32];

    for(int i = 0; i < InstCnt; i++)
	Instrums[i].QuoteValue = 0;

    char* Pnt = Buf;
    Pnt += 4 * sizeof(unsigned short);
    while(Pnt - Buf < BufSize) {
	if(*(unsigned char*)Pnt == (unsigned char)0) {
	     Pnt += sizeof(unsigned char);
	     continue;
	}
	BlockType = (int)(*(unsigned short*)Pnt);
	Pnt += 2 * sizeof(unsigned short);
	if(BlockType == 1) {
	    RealData = *(double*)Pnt;
	    for(int i = 0; i < InstCnt; i++) {
		TInstrum* Instr = Instrums + i;
		if(!strcmp(Instr->SrcName, StringData)) {
                   //сохраняем котировку для инструмента из массива выбранных в приложении инструментов.
  	 	      Instr->QuoteValue = RealData;
		      break;
		}
	    }
	    Pnt += sizeof(double);
	} else if(BlockType == 2) {
	    StringSize = (int)(*(unsigned char*)Pnt);
	    Pnt += 1;
	    if(StringSize >= 1) {
	        CopyMemory(StringData, Pnt, StringSize);
		StringData[StringSize] = (char)0;
	    }
	    Pnt += StringSize;
	}
    }
}
 
favoritefx >>:
Можно по ODBC получать любые данные из QUIK, а заявки отправлять через dll. Метод верный, неоднократно испробованный :)

что-то не совсем понял о чем речь. какие заявки?

предлагаете писать свой Odbc драйвер?

 
GarF1eld >>:

что-то не совсем понял о чем речь. какие заявки?

предлагаете писать свой Odbc драйвер?

Нет, драйвер писать не нужно, достаточно создать источник данных (я пробовал Access и MS SQL), зарегистрировать его в Windows, а затем из QUIK

запустить экспорт в этот источник данных, а из своего приложения уже эти данные и анализировать.

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

 
favoritefx >>:

Нет, драйвер писать не нужно, достаточно создать источник данных (я пробовал Access и MS SQL), зарегистрировать его в Windows, а затем из QUIK

запустить экспорт в этот источник данных, а из своего приложения уже эти данные и анализировать.

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

это достаточно косвенный вариант, тем более он мне не подходит, например если данные обновляются достаточно быстро, то не все будут учтены.

хотя в случае с MS SQL по идее должна работать связка Quik -> Odbc -> MS SQL -> Триггер на INSERT -> .NET assembly -> Приложение :D Но это издевательство, тем более если захочется сменить базу, например на оракл то уже не катит.


c другой стороны я могу не понимать о чем говорю ибо даже представления не имею в каком виде данные выводятся в базу. предполагаю что в таком же как и в эксель


а вот вариант elrtimo мне больше понравился. Спасибо, работает!!

Правда еще не разобрался где таблица Last quote в quike, но callback-и в приложении вызываются, уже хорошо.


Единственная проблема, я не смог запустить эксель, если запущена моя прога. Видимо он ищет приложение с зарегистрированным
DDE сервером с именем EXCEL и если находит, то не запускается. Может кто подскажет как этого избежать.

Знаете, у меня подобной проблемы не возникло: вместо EXCEL пишу любую понравившуюся мне строку. а потом в квике при экспорте в поле dde-сервер просто указываю её. и работает. и эксель запускается


PS. Если кто-то заинтересован в коде на c#, то могу выложить попозже

 

Ну там в квике можно создать таблицу в которую можно добавить инструмент и выбранный параметр. Так вот я выбрал Last Quote или "последняя котировка", а для индекса RTSI и MICEX выбирал Value потому как последняя котировка не изменяется для этих инструментов. Вообщем в таблице должно быть наименование инструмента и значение котировки.

С подходом ODBC вероятно не надо буфер приходящий парсить. Если в таблице в квике которую выводишь по DDE название инструмента и значение котировки то нет проблем.

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

Кстати тоже заменю имя сервера EXCEL. Спасибо за подсказку.

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