← Zurück

BaseTrader.MartketTime, предложение

Вначале немного предыстории - в последнее время заметил задержки в получение времени средствами QuikTrader.MartketTime - в квике в ходе торгов секунды зачастую идут с задержкой 1-3 секунды, да и отсчёт идёт не каждую секунду. В общем не очень хорошо, на мой взгляд, использовать данное решение.

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

Поэтому появилась идея использовать не системное время (т.к. оно может:

  • быть не синхронизировано
  • быть не московским, ....), а московское время из интернета.

Т.е. обращаться к стандартными NTP серверам и опрашивая их получать московское время.

Поискав в инете наткнулся на множество тем, выбрал решение отсюда как наиболее простое: всемогущий MSDN

Немного его отредактировал под наши нужны, получил следующее:

using System;
using System.Net;
using System.Net.Sockets;

namespace Robots.Entities
{
    /// <summary>
    /// Static class to receive Moscow time from a NTP server.
    /// </summary>
    public static class NtpClient
    {
        /// <summary>
        /// Gets Moscow DateTime from <paramref name="ntpServer"/>.
        /// </summary>
        /// <param name="ntpServer">The hostname of the NTP server.</param>
        /// <returns>A DateTime containing Moscow current time.</returns>
        public static DateTime GetMoscowTime(string ntpServer = "time-a.nist.gov")
        {
            var address = Dns.GetHostEntry(ntpServer).AddressList;

            if (address == null || address.Length == 0)
                throw new ArgumentException(string.Format("Could not resolve ip address from '{0}'.", ntpServer), "ntpServer");

            var ep = new IPEndPoint(address[0], 123);
            return GetMoscowTime(ep);
        }

        /// <summary>
        /// Gets Moscow DateTime form <paramref name="ep"/> IPEndPoint.
        /// </summary>
        /// <param name="ep">The IPEndPoint to connect to.</param>
        /// <returns>A DateTime containing Moscow current time.</returns>
        private static DateTime GetMoscowTime(IPEndPoint ep)
        {
            var s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            s.Connect(ep);

            var ntpData = new byte[48]; // RFC 2030
            ntpData[0] = 0x1B;
            for (var i = 1; i < 48; i++)
                ntpData[i] = 0;

            s.Send(ntpData);
            s.Receive(ntpData);

            const byte offsetTransmitTime = 40;
            ulong intpart = 0;
            ulong fractpart = 0;

            for (var i = 0; i <= 3; i++)
                intpart = 256 * intpart + ntpData[offsetTransmitTime + i];

            for (var i = 4; i <= 7; i++)
                fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];

            var milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);
            s.Close();

            var timeSpan = TimeSpan.FromMilliseconds(milliseconds);

            var dateTime = new DateTime(1900, 1, 1);
            dateTime += timeSpan;

            var moscowTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");
            var offsetAmount = moscowTimeZone.GetUtcOffset(dateTime);
            var networkDateTime = dateTime + offsetAmount;

            return networkDateTime;
        }

        /// <summary>
        /// Gets TimeSpan offset.
        /// </summary>
        /// <returns>Gets offset between local time and Moscow Time.</returns>
        public static TimeSpan GetMoscowTimeOffset()
        {
            try
            {
                var moscowDateTime = GetMoscowTime();
                return moscowDateTime - DateTime.Now;
            }
            catch(Exception)
            {
                return new TimeSpan(0);
            }
        }
    }
}

NtpClient.GetMoscowTime("time.nist.gov") возвращает текущее московское время :) NtpClient.GetMoscowTimeOffset() - смещение с московским временем.

Предложение состоит в том, чтобы использовать данное время для определения BaseTrader.MarketTime. 1 раз - при инициализации получать московское время и просто подсчитать первоначальную разницу между московским временем и локальным. Затем установить его в MarketTimeOffset.

Вот текущее использование, которое я сегодня добавил в моего робота:

    public class OwnQuikTrader : QuikTrader
    {
        public OwnQuikTrader(string path, string ddeServer, string dllName) :
            base(path, ddeServer, dllName)
        {
            base.MarketTimeOffset = NtpClient.GetMoscowTimeOffset();
        }

//...

        public override DateTime MarketTime
        {
            get { return DateTime.Now; }
        }
    }

War dieses Thema hilfreich?

Thema teilen

Kommentare (13)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Alexander
Alexander Autor

Хотя, уходит время на отправку и получение запроса - поэтому результат не совсем точный, 1 секунды разницы набегает наверное. Но он всяко ближе чем через квик и доступен также из любой временной зоны.

a.dobryn
Alexander
Alexander Autor

Вот, нашёл проект, он позволяет избежать проблемы с задержкой на отправку \ получение - всё учитывает. CodeProject

Alexander
Alexander Autor

Начал реализовывать, но появилась сложность - для полной поддержки мы должны уметь обращаться к NTP серверу как через прокси, так и напрямую. Что довольно проблематично. Накладывать на S# сетевые возможности не хочется.

Есть другое предложение - по умолчанию в MarketTimeOffset записывать разницу между московским временем и локальным на компьютере (но её получим через временные зоны - +3 от москвы и зоной, установленной локально). Время будет всегда браться локальное - т.е. при необходимости надо будет самому обновить время на компьютере.

Сдаётся мне, что это довольно хороший выход, позволяющий обойти все недостатки нынешней реализации - то что либо надо самомуу устанавливать MarketTimeOffset, либо то что время берётся из Квика...

esper
esper

Думаю, что вариант неплохой

President
President

а кроме времени в Quik нет какого-нибудь биржевого времени? например, как сейчас определяется Trade.Time - оно разве не биржей заполняется?

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

Alexander
Alexander Autor

President: а кроме времени в Quik нет какого-нибудь биржевого времени? например, как сейчас определяется Trade.Time - оно разве не биржей заполняется?

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

Trade.Time - время сделки. Как предлагает с ним синхронизоваться? Время когда по DDE придёт сделка тоже не гарантировано.

President
President

Alexander:

President: а кроме времени в Quik нет какого-нибудь биржевого времени? например, как сейчас определяется Trade.Time - оно разве не биржей заполняется?

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

Trade.Time - время сделки. Как предлагает с ним синхронизоваться? Время когда по DDE придёт сделка тоже не гарантировано.

вот нашел сервер Name: ntp.rts.ru Address: 194.247.133.37 и моя винда даже смогла с ним ссинхронизироваться

2. ТЕОРЕТИЧЕСКИ можно самостоятельно сделать синхронизацию по полям Trade/Order таким же способом каким происходит синхронизация с NTP серверами. вот тут я нашел примерное описание "Принцип определения точного времени" http://time.in.ua/ntp.html т.о. если есть способ послать на биржу запрос и получить ответ с биржевым временем НАЧАЛА обработки запроса и временем ЗАВЕРШЕНИЯ его обработки (например время приема заявки и время ее исполнения) то это сделать можно.

...

А ведь на РТС и ММВБ время может различаться ;) с кем тогда синхронизироваться? Наверное и правда лучше дать возможность возможность каждому самому указать нужный ему NTP сервер

Alexander
Alexander Autor

President: т.о. если есть способ послать на биржу запрос и получить ответ с биржевым временем НАЧАЛА обработки запроса и временем ЗАВЕРШЕНИЯ его обработки (например время приема заявки и время ее исполнения) то это сделать можно.

я такой способ не знаю :)

EugeneP
EugeneP

President: 1. вот нашел сервер Name: ntp.rts.ru Address: 194.247.133.37 и моя винда даже смогла с ним ссинхронизироваться

pool.ntp.org юзайте. С ним вроде без проблем коннектится

EugeneP
EugeneP

Alexander:

Кстати, поздравляю с денюхой! Успехов 👍

Alexander
Alexander Autor

EugeneP;9680:

Alexander:

Кстати, поздравляю с денюхой! Успехов 👍

Спасибо большое :) 👍

EugeneP
EugeneP

через проксю думаю не многие инет пользуют, это в основном в корпоративных сетях используют, а роботостроители все таки думаю в большинстве своем вольные птицы, да и с работы робота запускать - как то.. не правильно на мой взгляд. Лучше добавить в s# поддержку синхронизации через NTP, чтобы можно было ее вызывать вручную, например при запуске робота, а уж те кто за проксей пусть сами синхронизируют. Тем более обычно в корпорациях время на раб станциях уже синхронизировано

Alexander
Alexander Autor

EugeneP: через проксю думаю не многие инет пользуют, это в основном в корпоративных сетях используют, а роботостроители все таки думаю в большинстве своем вольные птицы, да и с работы робота запускать - как то.. не правильно на мой взгляд. Лучше добавить в s# поддержку синхронизации через NTP, чтобы можно было ее вызывать вручную, например при запуске робота, а уж те кто за проксей пусть сами синхронизируют. Тем более обычно в корпорациях время на раб станциях уже синхронизировано

Ну код для NTP я привёл уже давно - см. первое сообщение. Кому необходимо - уже используют.

Вариант синхронизации по запросу тоже неплохой.