← 返回

Stock# с несколькими квиками

Со сколькими копиями квика можно безболезненно запускать одного робота? Как происходит экспорт через DDE в Stock# - одинаковые данные, я так понимаю, фильтруются?

Вопрос возник не случайно - сейчас с 7ми квиками роботы съедают до 50-60% от нашего довольно мощного сервера (на каждом квике запущен 1-2 робота, каждый робот запускается 1 секунду). Стоит ли искать ошибку, пытаться оптимизировать самого робота или лучше закинуть часть квиков на другой сервер?

本主题对您有帮助吗?

分享主题

评论 (48)

登录创建账户, 登录或注册以发表评论

Mikhail Sukhov
Mikhail Sukhov
  1. Да, одинаковые данные отбрасываются. Если это разные Квики, то это будут все сделки и инструменты (если конечно у Вас не шарица еще что- то). Хотя и сделки могут быть уникальными, если каждый Квик торгует только свой диапазон инструментов.
  2. А кто съедает? Робот или Квики? Роботов несколько или же он только один? Распределение 50-60 по прогам можете привести?
Maxim
Maxim

Mikhail Sukhov:

  1. Да, одинаковые данные отбрасываются. Если это разные Квики, то это будут все сделки и инструменты (если конечно у Вас не шарица еще что- то). Хотя и сделки могут быть уникальными, если каждый Квик торгует только свой диапазон инструментов.

Михаил, небольшое уточнение. Предположим используется MultiTrader с двумя разными Квиками. В этих Квиках настроены «Все сделки» и «Стаканы» для одной бумаги, например Сбера.

Выше Вы написали, что данные поступают от двух Квиков одновременно. Дублирующие данные учитываются и отбрасываются.

Верно ли это для «Стаканов»?

Alexander
Alexander 作者

Съедает сам робот. Он запущен только 1, просто там идёт работа со многими квиками. Что это за распределение и как его сделать? :)

Ещё я заметил следующее при работе с несколькими квиками - возьмём, к примеру, таблицу Всех сделок. Она передаётся насколько я понимаю из какого-то одного квика (к примеру, который был первым добавлен в AggregatedTrades), из остальных игнорируется. Как только теряется связь с сервером у первого квика (остальные при этом работают) - таблица всех сделок перестаёт экспортироваться (хотя могла бы из других квиков) - получается нельзя таким образом подстраховаться...

Mikhail Sukhov
Mikhail Sukhov

Можно через Process Explorer. Он покажет, какие потоки тормозят. А потокам можно понять, что в них делается. Все S# потоки именованы. Робота, если Вы этого не делали, не именованы.

Насчет прекращения экспорта. Схема не такая. Роботу льется все. А он уже смотрит на уникальность. Так что, если какой-то из Квиков лили дубли и он упал, то на экспорт это не должно отразиться. Тут случаем ReConnectionManager не вступает в работу? Вот он может все остальные Квики перезапускать.

Maxim
Maxim

Mikhail Sukhov: Насчет прекращения экспорта. Схема не такая. Роботу льется все. А он уже смотрит на уникальность. Так что, если какой-то из Квиков лили дубли и он упал, то на экспорт это не должно отразиться. Тут случаем ReConnectionManager не вступает в работу? Вот он может все остальные Квики перезапускать.

Насколько я понял из документации, для MultiTrader отсутствует ReConnectionManager. То есть выше Вы имели ввиду, что вступает в работу ReConnectionManager для одного из Квика, который используется в MultiTrader.

Как может ReConnectionManager одного Квика перезапустить все остальные Квики? Или я что то не понял?

Mikhail Sukhov
Mikhail Sukhov

Maxim: Как может ReConnectionManager одного Квика перезапустить все остальные Квики? Или я что то не понял?

С тех пор много воды утекло.

Maxim
Maxim

Mikhail Sukhov:

Maxim: Как может ReConnectionManager одного Квика перезапустить все остальные Квики? Или я что то не понял?

С тех пор много воды утекло.

То есть ситуация уже другая и ReConnectionManager пользовать можно?

А на предыдущий вопрос какой ответ? Насчет информации из стакана, если два Квика работают.

Mikhail Sukhov
Mikhail Sukhov

Maxim:

Mikhail Sukhov:

Maxim: Как может ReConnectionManager одного Квика перезапустить все остальные Квики? Или я что то не понял?

С тех пор много воды утекло.

То есть ситуация уже другая и ReConnectionManager пользовать можно?

А на предыдущий вопрос какой ответ? Насчет информации из стакана, если два Квика работают.

Лучше чтобы пересечение не было.

Maxim
Maxim

Mikhail Sukhov: Лучше чтобы пересечение не было.

Скупы Вы, Михаил, на слова. 🙂

Но всеже повытягиваю информацию из Вас еще 🙂

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

Необходимо использовать суммарную их информацию. Для этих целей, насколько я понял, подходит MultiTrader. Хотелось бы узнать подводные камни.

Какие еще тонкости в использовании MultiTrader с несколькими Квиками, настроенными на одну и ту же бумагу? В чем сложность со стаканом? Почему «лучше чтобы пересечение не было»?

Может быть Alexander поможет с ответом?

Mikhail Sukhov
Mikhail Sukhov

Maxim: Скупы Вы, Михаил, на слова. 🙂

Я не скуп. Мне теперь приходится отвечать и новичкам и старичкам. Новичкам отвечаю больше. За счет ответов старичкам. Так что если старички хотят повысить качество ответов себе любимым, нужно повышать количество ответов новичкам.

Maxim: Но всеже повытягиваю информацию из Вас еще 🙂

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

Необходимо использовать суммарную их информацию. Для этих целей, насколько я понял, подходит MultiTrader. Хотелось бы узнать подводные камни.

Какие еще тонкости в использовании MultiTrader с несколькими Квиками, настроенными на одну и ту же бумагу? В чем сложность со стаканом? Почему «лучше чтобы пересечение не было»?

Может быть Alexander поможет с ответом?

Я несколько Квиков не использовал. Да, думаю Александр тут более компетентен.

Alexander
Alexander 作者

ðÏËÁÚÁÌ, ÔÏÒÍÏÚÉÔ LogHelp, ×ÏÔ StackTrace: ntkrnlpa.exe!NtBuildNumber+0xe ntkrnlpa.exe!RtlUpcaseUnicodeString+0xa2 ntkrnlpa.exe!ZwYieldExecution+0x4f3 ntkrnlpa.exe!MmIsDriverVerifying+0xbb2 hal.dll+0x2ef2 clr.dll+0x1a5e clr.dll!CoUninitializeEE+0x378e clr.dll!CoUninitializeEE+0x7663 clr.dll!LogHelp_TerminateOnAssert+0x6a1fd clr.dll!LogHelp_TerminateOnAssert+0x3c642 clr.dll!LogHelp_TerminateOnAssert+0x3c560 clr.dll!LogHelp_TerminateOnAssert+0x3c6de clr.dll!LogHelp_TerminateOnAssert+0x40b22 clr.dll!LogHelp_TerminateOnAssert+0x3aab2 mscorlib.ni.dll+0x2aae5b mscorlib.ni.dll+0x237ff4 mscorlib.ni.dll+0x237f34 mscorlib.ni.dll+0x2aade8 clr.dll+0x21db clr.dll!CoUninitializeEE+0x6862 clr.dll!CoUninitializeEE+0x6a04 clr.dll!CoUninitializeEE+0x6a39 clr.dll!GetPrivateContextsPerfCounters+0x8a13 clr.dll!LogHelp_TerminateOnAssert+0x591ad clr.dll!LogHelp_TerminateOnAssert+0x5922f clr.dll!LogHelp_TerminateOnAssert+0x592ea clr.dll!LogHelp_TerminateOnAssert+0x59381 clr.dll!GetPrivateContextsPerfCounters+0x88e6 clr.dll!GetPrivateContextsPerfCounters+0x87e1 clr.dll!LogHelp_TerminateOnAssert+0x58fb0 KERNEL32.dll!GetModuleFileNameA+0x1ba

ReConnectionManager, ËÏÎÅÞÎÏ, ×ÓÔÕÐÁÅÔ × ÒÁÂÏÔÕ ÅÓÌÉ ÏÄÉÎ ÉÚ Ë×ÉËÏ× ÕÐÁÌ, Á ÄÒÕÇÏÊ - ÎÅÔ. ô.Å., ×ÉÄÉÍÏ, ÓÔÏÉÔ ReconnectionManager ÎÁÚÎÁÞÁÔØ ÏÔÄÅÌØÎÏ ÄÌÑ Ë×ÉËÏ×, Á ÎÅ ÄÌÑ ×ÓÅÇÏ MultiTrader?

Alexander
Alexander 作者

Отключил логгирование для стратегий (убрал обработчик OnLog и не добавляю StrategyLogger) - теперь робот ест от 0 до 50% процессора. 50% - крайне редко, всплески. в основном висит на 0%. т.е. разница колоссальная.

Mikhail Sukhov
Mikhail Sukhov

Хм, или логов много или дисковая операция тяжелая. Есть вероятность что StrategyLogger глючит, он там так мало кода. Фактически, вот он весь (что используется при активизации события):

_writer = new StreamWriter(logDirectory.IsEmpty() ? this.FileName : Path.Combine(logDirectory, fileName)) ;

private void StrategyLog(Strategy strategy, StrategyErrorStates state, string message) { WriteMessage(strategy + " " + message);

///

/// Записать специальное сообщение, которое относится ко всем статегиям . /// /// Сообщение. public void WriteMessage(string message) { if (message.IsEmpty()) throw new ArgumentNullException("message");

   Debug.WriteLine(message);
    _writer.WriteLine("{0} {1}", DateTime.Now.TimeOfDay, message);
Иванов Андрей
Иванов Андрей

Про тяжёлую дисковую операцию не понял =) Дисковые операции едят время (iowait), а не CPU.

Про много лог-записей в точку -- операция конкатенации самая дорогая по CPU в .NET (из тех, что не ожидаешь). Единственный способ борьбы это писать сразу в файл. Если убрать конкатенацию в _writer.WriteLine(..), производительность логирования вырастет в полтора раза =)

То есть, оформить запись в виде трёх вызовов -- время, разделитель, сообщение.

Захотите проверить мою теорию, включите логирование, а все строки с конкатенацией замените на строки-константы примерно той же длины.

Ещё эффективнее по CPU будет, если событие лога генерировать не со строкой конкатенации стратегии и сообщения, а объектом с двумя полями или вызовом метода с двумя параметрами.

Единственный вариант привязать к CPU запись на диск это отключить DMA для ATA-дисков. Я никогда не сталкивался с необходимостью такое делать, но можно попровать начать с этого -- проверять надо в дисковом контроллере, на всех системах названия свои. Раньше было переключение между режимами (PIO/*DMA), в семёрке чекбокс выключения DMA.

Alexander
Alexander 作者

логов много - каждая запущенная стратегия каждую секунду что-то да пишет. про тяжёлую дисковую операцию я тоже не понял =)

Хотелось бы ещё закрыть вопрос с прекращением экспорта - я так понимаю в случае с MultiTrader необходимо ReconnetionManager создавать для каждого из добавленных AggregatedTraders? В этом случае экспорт не прекратится если отвалится лишь один из квиков

Иванов Андрей
Иванов Андрей

У меня на процессоре Q6600 конкатенация съедала одно ядро примерно за 100 тысяч записей в секунду. Если у вас 100 стратегий с тайм-фреймом секунда, современный процессор не заметит этого -- тайм-фрейм должен быть 10 миллисекунд. У вас либо очень много стратегий (100 тысяч), либо они не все работают с тайм- фреймом, либо предположение о конкатенации неверно.

Посчитайте, сколько у вас записей в лог за секунду делается. Вместо записи в лог инкрементируйте счётчик через

Interlocked.Increment(ref _logCounter);

и пишите это значение куда-нибудь раз в секунду примерно вот так:

int count = Interlocked.Exchange(ref _logCounter, 0); Console.WriteLine("Log rps: {0}", count);

_logCounter -- глобальная переменная. Стратегии вроде сами по себе ничего не пишут в лог, поэтому вы можете получить точное значение.

Mikhail Sukhov
Mikhail Sukhov

private class MyStrategy : Strategy { public void DoLog(string message) { base.AddLog(StrategyErrorStates.None, message); }

   protected override bool OnProcess()
    {
            return false;
    }

var str = new MyStrategy();

var logger = new StrategyLogger("1.txt"); logger.Strategies.Add(str);

const int count = 100000;

var t1 = Watch.Do(() => { for (var i = 0; i < count; i++) { str.DoLog("111"); }

logger.Strategies.Remove(str);

var writer = new StreamWriter("2.txt") ;

str.Log += (s, e, m) => { writer.Write(DateTime.Now.TimeOfDay); writer.Write(" "); writer.Write(s); writer.Write(" "); writer.WriteLine(m);

var t2 = Watch.Do(() => { for (var i = 0; i < count; i++) { str.DoLog("111"); }

ňĹÚŐĚŘÔÁÔ ÎÁ ÍĎĹÍ ÍÁŰÉÎËĹ. t1 - 55 ÓĹËŐÎÄ. t2 - 1 ÓĹËŐÎÄÁ. îÉŢĹÇĎ ÓĹÂĹ! áÎÄŇĹĘ, ÖÄŐ ËĎÍÍĹÎÔÁŇÉĘ. đĎÔĎÍŐ ËÁË Ń ÄĎ ÓÉČ ĐĎŇ ÓŢÉÔÁĚ, ŢÔĎ ĎĐĹŇÁĂÉŃ ÚÁĐÉÓÉ × ĆÁĘĚ ÍÎĎÇĎ ÄĎŇĎÖĹ ËÁËĎĘ-ÔĎ ËĎÎËÁÔĹÎÁĂÉÉ ÓÔŇĎË.

Mikhail Sukhov
Mikhail Sukhov

Можете сделать проще. Отнаследоваться от QuikTrader, переопределить ReStartExport и там прописать свою логику проверки - нужно перезапускать экспорт или не нужно.

Иванов Андрей
Иванов Андрей

Комментарий о чём? ;) У вас синтетический случай, поэтому такой огромный прирост.

Если вопрос "почему?", то потому что когда пишете сразу в файл, копирование в памяти всего одно, а когда у вас несколько раз осуществляется операция конкатенации, вы копируете данные много раз. Из неочевидного строки создаются на хипе, а не на стеке, их создаётся много и GC освобождает занимаемую ими память. В случае 2 выделения/ освобождения памяти практически нет, все данные в кэше процессора, поэтому он работает на максимальной скорости, а не спотыкается об ожидание данных из медленной памяти.

Ну а запись в файл, как вы уже заметили, происходит очень быстро =) Потому что вывод буферизованный -- когда вы делаете 5 вызовов вместо одного, они все пишут в один буфер и оверхеада по сравнению с записью всей строки одним вызовом почти нет.

Если будете увлекаться файлами, столкнётесь с ещё одной неочевидной штукой. Называется IOPS. Пока читаете/пишете линейно, скорости обычного SATA будет достаточно -- придумана куча технологий для ускорения линейного доступа (кэши, буферы, группировка вызовов операционной системой, NCQ), но как только чтение станет случайным, пиковые 400-500 IOPS SAS-диска за тысячу долларов покажутся жалкой пародией на скорость =) Потому что в переводе на мегабайты получится чуть больше 10 мегабайтов в секунду, это в 10-15 раз меньше современного бытового SATA-диска на линейном доступе.

Mikhail Sukhov
Mikhail Sukhov

В том то и дело, что я устанавливаю AutoFlush = true. А это отключает всякую буферизацию. А если бы был буфер, я правильно понимаю, что сброс буфера в файл происходит асинхронно?

Насчет хипа - я так и думал. string - это ведь класс. Но ведь буферы у StreamWriter наверняка хранят не массив object, а массивы byte[]. Последние - это перевод переданных строк в файловой представление. Так вот, а массивы так же хранятся в хипе, и так же нужно время на перевод из строки в byte[]. Где же тогда экономия?

Про рандом и последовательный доступ понятно. Я читал об этом раньше. Надеюсь в S# не придется с этим столкнутся. Не хотелось бы погрязнуть в системных тонкостях =)

Иванов Андрей
Иванов Андрей

AutoFlush занимается тем, что сбрасывает буферы самого StreamWriter в подлежащий стрим. Использование этого флага с файлами ничего не меняет. Писать можно без буферов, потому что под StreamWriter должен быть какой-то FileStream, который сам будет буферизовать вывод, плюс есть буфер ядра.

Выключить буферизацию в ядре можно только ключом в реестре на всю систему или открывая файл. Отключить буфер после открытия файла, по- моему, невозможно -- необходимость буферизации известна до использования файла. По умолчанию буфер ядра в Windows Server несколько мегабайтов, сколько он в десктопах, не знаю. В десктопах и серверах разные схемы кэширования и буферов по умолчанию, в серверах сейчас (2008/2008R2) кэширование по умолчанию может съесть всю память и программам придётся свапиться =)

Сброс буфера ядра асинхронный. Сбросы прикладных буферов синхронные.

Массивы буферов не создаются и не удаляются 100 тысяч раз в секунду =) Они один раз создаются и живут какое-то продолжительное время. Когда вы делаете s1 += s2;, вы создаёте один объект (результат конкатенации s1 и s2) и отдаёте GC один объект (тот, на который до операции указывал s1). В случае с буферами все остаются при своих, происходит только одно копирование. Самый шик, когда строка не помещается в Gen 0 и отправляется в LOH -- в этом случае основную часть процессорного времени занимает удаление объектов =) Но это не наш случай, потому что строка должна быть больше 40 тысяч обычных символов (а необычных, типа индийских, ещё на треть меньше).

Alexander
Alexander 作者

т.е. перезапускать экспорт только в том случае, если нет подключения:

public class OwnQuikTrader : QuikTrader { public OwnQuikTrader(string path, string ddeServer, string dllName) : base(path, ddeServer, dllName)

   public override void ReStartExport()
    {
        if (!IsConnected)
            base.ReStartExport();
    }
}

?

Mikhail Sukhov
Mikhail Sukhov

Да, так, если такого поведения достаточно.

Mikhail Sukhov
Mikhail Sukhov

Массив буферов создается один раз, согласен (возможно еще как-то увеличивается уменьшается, но это не так важно). Но сами то буферы нет. Они создаются так же часто, как мы вызываем Write. string в byte[] - создаем, int в byte[] - создаем, DateTime в byte[] - создаем... Тоесть, в любом случаем необходимо произвести конфертацию, а это создание массива байтов.

Копирование byte[] в массив буферов?

Иванов Андрей
Иванов Андрей

Не, массивы байтов не создаются, создаются строки. Много-много строк (иногда char[]).

Для начала форматная строка парсится (это TextWriter.Write).

public virtual void Write(string format, object arg0, object arg1) { this.Write(string.Format(this.FormatProvider, format, new object[] { arg0, arg1 }));

Из-за того, что выделенной памяти не хватило на создание конечной строки (размер форматной + 16 символов), происходит реаллок с выделением памяти в два раза больше и копированием. При парсинге форматной строки аллоки поменьше для внутреннего использования. Копирований, соответственно, пачка. Тут основная часть CPU и съедается.

Я писал сделки в файлы инструментов и каждый раз (запись сделки) считал путь к имени файла инструмента. Кэширование этой операции дало примерно пятикратный прирост скорости записи. Закэшировал остальные операции вычисления пути (тоже просто конкатенации и Path.Combine), прирост ещё раза в два.

Форматная строка вида

string dealStr = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}; {1:T};{2};{3};{4};{5}", _id, _timeStamp, _price, _count, _volume, _operation.HasValue ? _operation.ToString() : "0");

по скорости почти идентична просто конкатенации или StringBuilder. Предположу, что здесь хватило выделенного начального буфера (40 символов) и форматтер InvariantCulture работает быстрее CurrentCulture. Выяснять лениво, мне достаточно того, что так писать красивее, чем через + и работает некритично медленнее.

Писать напрямую в файл не стал, потому что после включения кэширования путей время полного копирования сделок за сутки составляет секунд 10. А если вместо форматной строки выше писать константу такой же длины, скорость пару секунд. 2 секунды или 10, роли не играет.

Alexander
Alexander 作者

Опять проблема возникла с запуском нескольких стратегий на нескольких квиках. Сейчас на сервере запущено 7 квиков и суммарно должно было бы запуститься 13 стратегий.

Я запускаю следующим образом:

//цикл по всем стратегиям //для каждой из стратегий получаю список из счетов для которых данная стратегия не была запущена TimeFrameStrategy tfStrategy = null; //в зависимости от стратегии tfStrategy инициализирую конструктором нужного класса (наследуемого как раз от TimeFrameStrategy) //регистрирую ТФ

tfStrategy.Log += Strategy_OnLog; var newDateTimeDir = string.Format("Logs\{0}{1:00}{2:00}", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day); if (!Directory.Exists(newDateTimeDir)) { Directory.CreateDirectory(newDateTimeDir);

var logger = new StrategyLogger("{0}\_{1} _{2}.txt".Put(newDateTimeDir, Enum.GetValues(typeof (StrategiesName)).GetValue(i), account.Account)); logger.Strategies.Add(tfStrategy);

_strategyManager.Register(tfStrategy, port, riFut); // где port - портфель нужный, riFut - фьюч из Securities. и то и то не null tfStrategy.Start();

В результате у меня для всех 13 стратегий создаются логи, но работают не все (в разные запуски разное число, от 4 до 8 было) - в логе неработающих стратегий лишь строчка 11:06:42.8281250 Volume_1_01:00:05 Volume_1 запущена. и ничего более, хотя при каждом вызове OnProcess в лог должно что-то писаться.

Вот сейчас в 8 стратегиях из 13 пишется, в 5 - лишь 1 эта строчка.

С чем это связано?

Alexander
Alexander 作者

Попробовал запускать стратегии после того, как добавил их в StrategyManager - не помогло, последние 5 из добавленных стратегий всё равно не работают - в лог пишут лишь 1 строку.

Alexander
Alexander 作者

Оказывается, это было связано с тем, что не хватало потоков для StrategyManager (я использовал конструктор без параметра для числа потоков) - получал на выходе лишь 8 потоков. Сегодня попытался создавать и указывать 15 потоков - всё заработало. Только непонятно насколько в таком случае он быстро будет работать =)

Есть небольшая просьба - можно ли в случае если используется конструктор StrategyManager по умолчанию (в который передаётся лишь ITrader) в случае, если число добавленных стратегий больше, чем число потоков, автоматически разбрасывать стратегии по потокам и запускать несколько стратегий на одном ядре? А то такой тихий незапуск стратегий как у меня очень смущает, проблема не очевидна первоначально.

Mikhail Sukhov
Mikhail Sukhov

Не, проблема в пуле потоков. Должно обрабатывать необработанные, а обрабатывает - обработанные. Ок, посмотрю.

Maxim
Maxim

Alexander, поделитесь опытом как работается с несколькими Квиками?

Интересует ситуация, когда в Квиках настроены одинаковые бумаги. Одна из задач использования MultiTrader - это минимизировать сделать поступление информации более стабильной. Что бы при задержках или падении части роботов программа все равно получала актуальные данные.

Реализовывать MultiTrader у себя в программе еще не начал. Возможно будут более конкретные вопросы. Пока могу задать такие:

  1. Какие подводные камни стоит учесть? На что обратить внимание?
  2. Предположим используется MultiTrader с двумя разными Квиками. В этих Квиках настроены «Все сделки» и «Стаканы» для одной бумаги, например Сбера. Выше Вы написали, что данные поступают от двух Квиков одновременно. Дублирующие данные учитываются и отбрасываются. Верно ли это для «Стаканов»? 3)Нормально ли теперь работает ReConnectionManager? Можно ли его использовать, если один из Квиков упадет?
Alexander
Alexander 作者

Maxim: Alexander, поделитесь опытом как работается с несколькими Квиками?

Интересует ситуация, когда в Квиках настроены одинаковые бумаги. Одна из задач использования MultiTrader - это минимизировать сделать поступление информации более стабильной. Что бы при задержках или падении части роботов программа все равно получала актуальные данные.

Реализовывать MultiTrader у себя в программе еще не начал. Возможно будут более конкретные вопросы. Пока могу задать такие:

  1. Какие подводные камни стоит учесть? На что обратить внимание?
  2. Предположим используется MultiTrader с двумя разными Квиками. В этих Квиках настроены «Все сделки» и «Стаканы» для одной бумаги, например Сбера. Выше Вы написали, что данные поступают от двух Квиков одновременно. Дублирующие данные учитываются и отбрасываются. Верно ли это для «Стаканов»? 3)Нормально ли теперь работает ReConnectionManager? Можно ли его использовать, если один из Квиков упадет?

Я использую MultiTrader лишь как коллекцию квиков. Фактически работа ведётся с каждым QuikTrader отдельно. ReConnectionManager устанавливается для каждого квика, поэтому если один падает - другие-то работают. Экспорт запускается для каждого квика отдельно. Опять же - сделано для того, чтоб при падении одного квика с данными, другие нормально работали. В стратегиях используются непосредственно нужные QuikTrader. MultiTrader используется для получения событий в основном о непрошедших сделках и т.д. и т.п. Может я неоптимально его использую, но пришёл именно к такому решению - как раз для того чтобы постоянно было дублирование данных для пущей стабильности.

Maxim
Maxim

Alexander, спасибо за ответ. Не совсем Вас понял. Еще немножко уточню.

  1. Настроены ли у Вас во всех Квиках одинаковые бумаги? Например, во всех четырех Квиках идет вывод тикков и стаканов для Сбера.

  2. Используете ли Вы свойство Trades из MultiTrader, или используете это свойство у каждого Квика?

3)Используете ли Вы метод GetMarketDepth из MultiTrader, или используете этот метод у каждого Квика?

Alexander
Alexander 作者

Maxim: Alexander, спасибо за ответ. Не совсем Вас понял. Еще немножко уточню.

  1. Настроены ли у Вас во всех Квиках одинаковые бумаги? Например, во всех четырех Квиках идет вывод тикков и стаканов для Сбера.

  2. Используете ли Вы свойство Trades из MultiTrader, или используете это свойство у каждого Квика?

3)Используете ли Вы метод GetMarketDepth из MultiTrader, или используете этот метод у каждого Квика?

  1. Да, конечно. Каждый квик работает с одинаковыми стратегиями и с одинаковыми бумагами.
  2. Стратегию я регистрирую используя конкретный необходимый QuikTrader. Поэтому Trades используется из него, а не из MultiTrader
  3. GetMarketDepth я вызываю для каждого квика - для дублирования данных в случае если один из квиков упадёт чтоб работа продолжалась.
Maxim
Maxim

Alexander: 2) Стратегию я регистрирую используя конкретный необходимый QuikTrader. Поэтому Trades используется из него, а не из MultiTrader 3) GetMarketDepth я вызываю для каждого квика - для дублирования данных в случае если один из квиков упадёт чтоб работа продолжалась.

Правильно я понимаю, что если один Квик упадет, то стратегия которая ему соответствует перестанет работать?

Alexander
Alexander 作者

Maxim:

Alexander: 2) Стратегию я регистрирую используя конкретный необходимый QuikTrader. Поэтому Trades используется из него, а не из MultiTrader 3) GetMarketDepth я вызываю для каждого квика - для дублирования данных в случае если один из квиков упадёт чтоб работа продолжалась.

Правильно я понимаю, что если один Квик упадет, то стратегия которая ему соответствует перестанет работать?

Да. Т.к. данные в него перестанут поступать. Но все остальные квики с этой стратегией будут работать. Опережая вопрос - как сделать автоматическое дублирование данных я не знаю :)

Вообще наверное MultiTrader как раз и должен это делать.

Maxim
Maxim

Alexander: Опережая вопрос - как сделать автоматическое дублирование данных я не знаю :) Вообще наверное MultiTrader как раз и должен это делать.

Я же в этом ключе и веду весь диалог :) Пытаюсь выяснить, как Вы используете MultiTrader для собирания одинаковых, дублирующихся данных со всех квиков, а потом использования этих данных из MultiTrader.

Вообщем, насколько я теперь понял, MultiTrader в этом ключе никто не использовал. Придется наступать на грабли самому.

Alexander
Alexander 作者

Удалил предыдущий ответ, был неправ. Сейчас пересмотрел код - MultiTrader фильтрует сделки по уникальности trade.ID (если стоит флаг SupportTradesUnique). Если флаг не стоит - фильтрации не будет. Остальные данные суммируются. Подписка на события происходит для каждого из квика при добавлении его в AggregatedTraders.

Также не забывайте, что у каждого trade есть поле Security. А оно будет разным для разных квиков (из-за Security.Trader).

Maxim
dart
dart

Добрый день, Работаю одним роботом с двумя квиками. И данные с ТВС первого квика приходят с запозданием. Например, сегодня на 17 часов последний тик был от 16 ч 11 мин. Во втором квике все тики прищли вовремя. Может проще запустить два робота отдельно на каждый квик? ЗЫ. наблюдал это на версиях 2.6.2 и 3.1.8

Alexander
Alexander 作者

dart: Добрый день, Работаю одним роботом с двумя квиками. И данные с ТВС первого квика приходят с запозданием. Например, сегодня на 17 часов последний тик был от 16 ч 11 мин. Во втором квике все тики прищли вовремя. Может проще запустить два робота отдельно на каждый квик? ЗЫ. наблюдал это на версиях 2.6.2 и 3.1.8

Как строится работа с двумя квиками? Как определяется задержка? У меня в настоящий момент работает 6 квиков, 1 робот, задержек не наблюдаю.

dart
dart

Alexander: Как строится работа с двумя квиками? Как определяется задержка? У меня в настоящий момент работает 6 квиков, 1 робот, задержек не наблюдаю.

  1. Как обычно, объявляю два квика. Без использования Multitrader.
  2. Смотрю сделки методом Filter. Смотрю дату последнего тика.
Alexander
Alexander 作者

dart:

Alexander: Как строится работа с двумя квиками? Как определяется задержка? У меня в настоящий момент работает 6 квиков, 1 робот, задержек не наблюдаю.

  1. Как обычно, объявляю два квика. Без использования Multitrader.
  2. Смотрю сделки методом Filter. Смотрю дату последнего тика.

2 QuikTrader? DDE разные? Используйте MultiTrader, там всё просто, не надо его бояться. :)

dart
dart

Alexander:

dart:

Alexander: Как строится работа с двумя квиками? Как определяется задержка? У меня в настоящий момент работает 6 квиков, 1 робот, задержек не наблюдаю.

  1. Как обычно, объявляю два квика. Без использования Multitrader.
  2. Смотрю сделки методом Filter. Смотрю дату последнего тика.

2 QuikTrader? DDE разные? Используйте MultiTrader, там всё просто, не надо его бояться. :) Конечно ДДЕ разные. S# сам же их переименовывает quik1 и quik2. Можно и Multitrader. Но у меня могут быть на разных квиках разные стратегии и разные объемы. Там же, я как понял, вся работа ведется только с одним созданным шлюзом Multitrader. Как там задавать разные объемы на разные квики?

Alexander
Alexander 作者

dart:

Alexander:

dart:

Alexander: Как строится работа с двумя квиками? Как определяется задержка? У меня в настоящий момент работает 6 квиков, 1 робот, задержек не наблюдаю.

  1. Как обычно, объявляю два квика. Без использования Multitrader.
  2. Смотрю сделки методом Filter. Смотрю дату последнего тика.

2 QuikTrader? DDE разные? Используйте MultiTrader, там всё просто, не надо его бояться. :) Конечно ДДЕ разные. S# сам же их переименовывает quik1 и quik2. Можно и Multitrader. Но у меня могут быть на разных квиках разные стратегии и разные объемы. Там же, я как понял, вся работа ведется только с одним созданным шлюзом Multitrader. Как там задавать разные объемы на разные квики?

Передавать в стратегии нужные Volume. Я, к примеру, меняю объём для каждой стратегии в каждом квике перед каждым входом - в зависимости от того сколько для данного счёта свободных средств. MultiTrader никак не влияет на то что на разных квиках будут разные стратегии, это очевидно что так будет.

dart
dart

Да я кажется понял. Попробую с Multitrader. Хотя всё равно не понятно почему с двумя QuikTrader сделки приходят не одинаково. Мне кажется проще иметь возможность самому задавать имя ДДЕ-сервера и запускать два отдельных робота на каждый квик. Хотя б для того чтобы можно было перезапускать один без ущерба для второго робота

Alexander
Alexander 作者

dart: Да я кажется понял. Попробую с Multitrader. Хотя всё равно не понятно почему с двумя QuikTrader сделки приходят не одинаково. Мне кажется проще иметь возможность самому задавать имя ДДЕ-сервера и запускать два отдельных робота на каждый квик. Хотя б для того чтобы можно было перезапускать один без ущерба для второго робота

что подразумевается под "два отдельных робота на каждый квик"? на один квик запускается один QuikTrader \ MultiTrader \ ..., в нём запускается 1 - тысячи Strategy, которые могут перезапускаться, останавливаться, как угодно взаимодействовать с квиком, без ущерба остальным стратегиям. 1 квик - 1 имя DDE. Иначе технология DDE не работает - лишь 1 вывод возможен.

dart
dart

Подразумевается полностью два отдельных робота на каждый квик. В каждом роботе у меня несколько стратегий. Имя ДДЕ -сервера - wrapper и его не изменить. Потому я и говорю, если б можно было менять: одному роботу задаю одно имя ДДЕ-сервера, другому другое и каждый работает со своим квиком не завися друг от друга.

Alexander
Alexander 作者

dart: Подразумевается полностью два отдельных робота на каждый квик. В каждом роботе у меня несколько стратегий. Имя ДДЕ -сервера - wrapper и его не изменить. Потому я и говорю, если б можно было менять: одному роботу задаю одно имя ДДЕ-сервера, другому другое и каждый работает со своим квиком не завися друг от друга.

А кто мешает это сделать? В любом случае имена DDE серверов обязаны быть разными для разных квиков. Отсюда и возникают проблемы. Пользуйтесь конструктором QuikTrader, передавая разные имена DDE для каждого Quik: дока

dart
dart

Спасибо. Не знал что есть возможность менять имя ДДе-сервера