А. Г.
А. Г. личный блог
01 июня 2016, 18:17

Код для формирования минуток из таблицы всех сделок квика для спота

Порядок действий

1. Формируем в квике таблицу всех сделок со следующими параметрами

Код для формирования минуток из таблицы всех сделок квика для спота

Фильтром отбираем нужные инструменты.

2. Скачиваем из Интернета свободно распространяемый DDE сервер от Морошкина с прилагаемыми dll.
3. В соответствующих местах кода заменяем код на вот этот

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Timers;
using System.Threading;
using XlDde;

namespace ConsoleApplication2
{
class Program
{
const string service = «myDDE»;
const string candleSPOT = «SPOT»;


static void Main(string[] args)
{

using (XlDdeServer server = new XlDdeServer(service))
{

server.AddChannel(candleSPOT, new SPOTChannel());
server.Register();

Console.WriteLine(«DDE server ready. Press Enter to exit.\n\n»);
Console.ReadLine();
}



}
}


// **********************************************************************
// * Классы DDE каналов с обработчиками данных *
// **********************************************************************


class SPOTChannel: XlDdeChannel
{
//static int time2 = 1000;
static int em = 7;
static int m = 1200;
static int[] NM = new int[em];
static int NMM = 0;
static int LastMinute = 0;
static int mm = 1638400;
static double[] Price_trade = new double[mm];
string[] EM_trade = new string[mm];
static int[] Time_trade_I = new int[mm];
static int[] Volume_trade = new int[mm];
static int[,] Time = new int[em,m];
static double[,] O = new double[em,m];
static double[,] H = new double[em,m];
static double[,] L = new double[em,m];
static double[,] C = new double[em,m];
static double[,] V = new double[em,m];

protected override void ProcessTable(XlTable xt)
{

//int time3 = 1000;
int[] nach = new int[em];
int nach1 = 0;
int i = 0;
int j = 0;
int s = 0;
int curHour = 0;
int curMin = 0;
int curDay = 0;
int curSec = 0;
int curDay_1 = 0;
string name;
string[] bf;
string[] EM = new string[em];
DateTime moment;
string[] Time_trade = new string[mm];

name = @«D:\Day2\Tiker_1.txt»;
try
{
StreamReader g = new StreamReader(name);

while ((name = g.ReadLine()) != null)
{
bf = name.Split(',');
for (i = 0; i < em; i++) EM[i] = Convert.ToString(bf[i]);

}
g.Close();
}
catch (FileNotFoundException e)
{
Console.WriteLine(e.Message);
Console.WriteLine(«Проверьте правильность имени файла!!!»);
}

catch (Exception e)
{
Console.WriteLine(«Ошибка:» + e.Message);
}


for (int row = 0; row < xt.Rows; row++)
{
for (int col = 0; col < xt.Columns; col++)
{
xt.ReadValue();
if (col == 0) Time_trade[row] = xt.StringValue;
if (col == 1) EM_trade[NMM] = xt.StringValue;
if (col == 2) Price_trade[NMM] = xt.FloatValue;
if (col == 3) Volume_trade[NMM] = xt.FloatValue;
moment = Convert.ToDateTime(Time_trade[row]);
int Hour = moment.Hour; int M = moment.Minute; int S = moment.Second;
Time_trade_I[NMM] = Hour * 100 + M;
}

curHour = DateTime.Now.Hour;
curMin = DateTime.Now.Minute;
curDay = curHour * 100 + curMin;

 

if (curDay < 1900) { if (Time_trade_I[LastMinute] == 1839 && (Time_trade_I[LastMinute] != Time_trade_I[NMM]) && s == 1) { LastMinute = NMM; for (i = 0; i < em; i++) NM[i]++; s = 0; } }


if ((Time_trade_I[LastMinute] != Time_trade_I[NMM]) && (NMM != LastMinute))
{

for (j = 0; j < em; j++)
{ Time[j, NM[j]] = Time_trade_I[LastMinute]; C[j, NM[j]] = 0; H[j, NM[j]] = 0; L[j, NM[j]] = 1000000; O[j, NM[j]] = 0; V[j,NM[j]]=0;}

for (i = LastMinute; i < NMM; i++)

{

for (j = 0; j < em; j++)
{

if (EM[j] == EM_trade[i])
{
if (O[j, NM[j]] == 0) { O[j, NM[j]] = Price_trade[i]; H[j, NM[j]] = Price_trade[i]; L[j, NM[j]] = Price_trade[i]; C[j, NM[j]] = Price_trade[i]; V[j,NM[j]]=Volume_trade[i];}

else { H[j, NM[j]] = Math.Max(H[j, NM[j]], Price_trade[i]); L[j, NM[j]] = Math.Min(L[j, NM[j]], Price_trade[i]); C[j, NM[j]] = Price_trade[i]; V[j,NM[j]]+=Volume_trade[i];}
}

}

}

for (j = 0; j < em; j++) { if (O[j, NM[j]] != 0) NM[j]++; }
LastMinute = NMM;

curHour = DateTime.Now.Hour;
curMin = DateTime.Now.Minute;
curDay = curHour * 100 + curMin;

if (curMin == 0) curDay = (curHour — 1) * 100 + 60;


for (j = 0; j < em; j++)
{
nach1 = 0;

for (i = 1; i < NM[j]; i++) { if (Time[j,i] < Time[j,i — 1]) nach1 = i; }

if (curDay < 1849) { if (Time[j, nach1] == 959) nach[j] = nach1 + 1; else nach[j] = nach1; }

if (Time[j,NM[j] — 1] + 1 >= curDay || Time[j,NM[j] — 1] + 1 == 1400)
{


Console.WriteLine("{0,6},{1,6},{2,6},{3,6},{4,6},{5,6},{6,6},{7,6}", EM[j], Time[j,NM[j] — 1] * 100, O[j,NM[j] — 1], H[j,NM[j] — 1], L[j,NM[j] — 1], C[j,NM[j] — 1], Time[j,NM[j] — 1] + 1, curDay);


// Вдогонку напишем информацию о состоянии канала

Console.WriteLine("\nSPOT IsConnected: {0}, Data received: {1}\n", this.IsConnected, this.DataReceived);
}
}
}

curHour = DateTime.Now.Hour;
curMin = DateTime.Now.Minute;
curSec = DateTime.Now.Second;

curDay = curHour * 100 + curMin;
curDay_1 = curHour * 10000 + curMin * 100 + curSec;

if (curDay < 1900)
{

if (Time_trade_I[LastMinute] == 1839 && curDay < 1842 && curDay_1 > 183855)
{
for (j = 0; j < em; j++)
{ Time[j, NM[j]] = Time_trade_I[LastMinute]; C[j, NM[j]] = 0; H[j, NM[j]] = 0; L[j, NM[j]] = 1000000; O[j, NM[j]] = 0; V[j,NM[j]]=0; }

for (i = LastMinute; i < NMM; i++)

{

for (j = 0; j < em; j++)
{

if (EM[j] == EM_trade[i])
{
if (O[j, NM[j]] == 0) { O[j, NM[j]] = Price_trade[i]; H[j, NM[j]] = Price_trade[i]; L[j, NM[j]] = Price_trade[i]; C[j, NM[j]] = Price_trade[i]; V[j,NM[j]]=Volume_trade[i];}

else { H[j, NM[j]] = Math.Max(H[j, NM[j]], Price_trade[i]); L[j, NM[j]] = Math.Min(L[j, NM[j]], Price_trade[i]); C[j, NM[j]] = Price_trade[i]; V[j,NM[j]]+=Volume_trade[i];}
}

}

}
s = 1; Thread.Sleep(100);
}
}


NMM++;
}

curHour = DateTime.Now.Hour;
curMin = DateTime.Now.Minute;
curDay = curHour * 100 + curMin;

 

if (curDay < 1843 && curDay > 1839)
{
for (j = 0; j < em; j++)
{

nach1 = 0;

for (i = 1; i < NM[j]; i++) { if (Time[j, i] < Time[j, i — 1]) nach1 = i; }

if (curDay < 1849) { if (Time[j, nach1] == 959) nach[j] = nach1 + 1; else nach[j] = nach1; }


Console.WriteLine("{0,6},{1,6},{2,6},{3,6},{4,6},{5,6},{6,6},{7,6}", EM[j], Time[j, NM[j]] * 100, O[j, NM[j]], H[j, NM[j]], L[j, NM[j]], C[j, NM[j]], Time[j, NM[j]] + 1, curDay);
// Вдогонку напишем информацию о состоянии канала

Console.WriteLine("\nSPOT IsConnected1: {0}, Data received: {1}\n", this.IsConnected, this.DataReceived);
}

Thread.Sleep(100);
}


}
}
// **********************************************************************
}


4. Меняем константу em на выбранное число эмитентов
5. Делаем файл Tiker_1.txt с нужными кодами эмитентов через запятую и кладем в нужную директорию. Меняем путь с D:\Day2\Tiker_1.txt на тот, который у Вас на компе.
6. Делаем консольное приложение в VS.
7. Настраиваем вывод по DDE из таблицы всех сделок (п. 1) как показано на следующем рисунке

Код для формирования минуток из таблицы всех сделок квика для спота

8. Запускаем консольное приложение.
Вот как выглядит это приложение на экране Вашего монитора

Код для формирования минуток из таблицы всех сделок квика для спота
Собственно все, теперь в приложении в массивах Time[j, i]; C[j, i] = 0; H[j, i]; L[j,i]; O[j, i]; V[j,i]; i от nach[j] до NM[j]-1 находятся время, Сlose, High, Low, Open и Volume текущих минуток для j-го эмитента без предторгового аукциона. В 18:43МСК в этих массивах будет полный набор внутридневных минуток без предторгового и послеторгового аукциона. Можно делать с ними, что нужно. И никаких купайлов, луа и стокшарпов.

P. S. Если «поиграть» с условиями по времени с учетом клирингов, то по аналогии можно и минутки с ФОРТСа делать.
22 Комментария
  • Евгений Черных
    01 июня 2016, 18:43
    Главный вопрос. А зачем? Минутки в самом квике не кошерные?
  • Karim
    01 июня 2016, 18:49
    На Lua это выглядит несколько проще.
  • Karim
    01 июня 2016, 18:54
     

    local quantity = 100
    local ind = «SiZ»

    IsRun = false
    begin = false

    function main()

    IsRun = true
    r=false
    begin = true

    while begin do
    n = getNumCandles(ind)--кол-во свечек, где ind = идентификатор графика
    t, res, _ = getCandlesByIndex (ind, 0, n — quantity, quantity)--получить последние n свечей (для справки)
    if res > 0 then
    r=wind.Test(t)
    begin = false
    end
    sleep(2000)
    end

    while IsRun do
    sleep(2000)
    end
    end


    А в проге в функции Test забираете из стека таблицу со свечками.
  • Nemo_2000
    01 июня 2016, 18:56
    ну, биржевые котировки формируются на основе происходящих сделок. какого хрена брать эти сделки и делать самому работу, которая уже выполнена терминалом?
    • Karim
      01 июня 2016, 19:01
      Nemo_2000, Если брать данные из таблицы всех сделок, а не с графика, то в квике получается быстрее. Такое впечетление, что в квике графики строятся с задержкой.
  • finstrateg
    01 июня 2016, 19:04
    Очень сложно — на луа попроще было бы ..., да и не очень понятно — зачем самому лепить минутки, если терминал этим занимается )))
      • finstrateg
        01 июня 2016, 19:37
        А. Г., да, интересно, как ведет себя в луа «приемник» данных — надо как-нибудь проверить, я котировки через CreateDataSource получаю, может оказаться актуальным для неликвида.
      • Барсуков Андрей
        01 июня 2016, 19:48
        А. Г., в 6 версии квика таблица всех сделок для спота реализована?

          • Барсуков Андрей
            02 июня 2016, 09:38
            А. Г., спасибо, уточню у брокера, у меня строит только ФОРТС
      • swerg
        01 июня 2016, 20:55
        А. Г.
        >В моей программе минутка появляется только после появления в таблице всех сделок,
        > сделки из следующей минуты хотя бы по одному из выбранных эмитентов.

        На сколько я помню, этот кейс уже разбирался на форуме квика.
        «Все сделки» тоже могут приходить не подряд. Это особенность рассылки информации биржей, так что смысла городить нет.
          • Prophetic
            02 июня 2016, 11:15
            А. Г., Вы уже неоднократно озвучивали причину по которой вынуждены были перейти на формирование минуток по таблице всех сделок, но если я правильно Вас понял, то случилось это тогда, когда еще не было CreateDataSource (если ошибаюсь — поправьте меня). В связи с чем вопрос: А не пробовали Вы сравнить «свои» минутки, с данными из CreateDataSource? Мне кажется, что там вероятность появления замеченной Вами проблемы должна быть значительно ниже (если не исключена вообще).
              • Prophetic
                02 июня 2016, 14:16
                А. Г., Понял, спасибо.
                Для информации (не уверен, что захотите этим заняться): На сегодняшний день необходимость использования DDE сервера у меня отпала. Нашел проект с открытым кодом QuikSharp, и тоже перевел всех роботов на C#. DDE сервер поднимать не нужно, Держать открытые таблицы в квике тоже не нужно.
                  • Prophetic
                    03 июня 2016, 09:33
                    А. Г., Я вынужден был перейти на C# тоже по причине жутких тормозов квика, когда в нем работало одновременно больше десятка роботов на Lua. Сейчас вся расчетная нагрузка вынесена за пределы терминала. В самом квике у меня запущена только вспомогательная прога на Lua, которая идет в комплекте с QuikSharp. Она запускается один раз и больше о ней уже не вспоминаешь. QuikSharp представляет из себя dll-ку, которая обеспечивает двухстороннюю связь с квиком (т.е. trans2quik тоже не нужен). через эту библиотеку можно принимать в свою программу любые market-data, доступные в самом квике, получать все колбеэки, и отправлять транзакции в квик. Это все, что нужно для создания практически любого робота. При этом, как я уже писал, нет никакой необходимости держать открытыми какие-либо таблицы в квике, но при желании можно получать данные непосредственно с открытых графиков (свечи, индикаторы).
  • b@e
    02 июня 2016, 12:03
    О боже, сколько кода!!! Практически — поэзия в цифрах.
  • mmm
    11 июля 2016, 23:40
    Я так понимаю, у квика клиента и сервера есть приоритеты — какие данные они передают сначала, а какие — потом. Сначала идут сделки, потом — стаканы, а потом только графики. И когда рынок резко дергается, загружается сразу много данных о сделках и изменения в стаканы, то графики могут притормознуть на несколько секунд, это очевидно и естественно, по-моему.
  • Вархан Джугурбаев
    17 сентября 2016, 20:15
    Если кому нужен квик или подобный другой терминал, можно взять на тестирование демку здесь: http://getanyplatform.com

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн