← Zurück

Закрытие позиций за 5 секунд до закрытия

Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи.

War dieses Thema hilfreich?

Thema teilen

Kommentare (34)

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

VassilSanych
VassilSanych

Сергей MenDel: Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи. Да вы, батенька, экстремал. Вы уверены, что вас исполнят в последние 5 секунд?

MenDel
MenDel Autor

VassilSanych:

Сергей MenDel: Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи. Да вы, батенька, экстремал. Вы уверены, что вас исполнят в последние 5 секунд? Я ща так руками закрываюсь, единственное приходится сверять часы на компе каждый день

Sergey Masyura
Sergey Masyura

Сергей MenDel: Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи.

Если без привязки в закрытому коду, то, например, Time scheduler in C#, By Aleksey Bykov, 16 May 2007.

http://www.codeproject.com/Articles/18633/Time-scheduler-in-C

MenDel
MenDel Autor

Sergey Masyura:

Сергей MenDel: Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи.

Если без привязки в закрытому коду, то, например, Time scheduler in C#, By Aleksey Bykov, 16 May 2007.

http://www.codeproject.com/Articles/18633/Time-scheduler-in-C

спс, ща посмотрим. Я ваще думал это в S# реализовано, вещь то нужная.

esper
esper

Часы в любом случае сверять придется. В S# можно попробовать посмотреть такую штуку.

MenDel
MenDel Autor

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

_trader.MarketTimeChangedInterval = TimeSpan.FromSeconds(1);
_trader.MarketTimeChanged += time1 => this.GuiAsync(() =>
                    {
                        var time = _trader.GetMarketTime(Exchange.Rts);
                        if (time.Hour == 23 && time.Minute == 49 && time.Second == 55) Button_ClosePosition_Click(null, null);
                    });
esper
esper

Сергей MenDel: ...

это конечно хорошо, но в настоящий момент GetMarketTime используется DateTime.Now, которое просто сдвинуто на часовой пояс указанной биржи.

developer_29
developer_29

... А напишите, пожалуйста, код метода Button_ClosePosition_Click. первые 2 строчки нужны для того, чтобы получать данные каждую секунду?

MenDel
MenDel Autor

developer_29: А напишите, пожалуйста, код метода Button_ClosePosition_Click. первые 2 строчки нужны для того, чтобы получать данные каждую секунду?

Первая строчка - чтоб каждую секунду, а вторая вызывает каждый раз метод Если по рынку закрывать, то делаю так

decimal position = 0;
            decimal price;
            OrderDirections orderDirections;

            try { position = _trader.Positions.FirstOrDefault(p => p.Security == SelectedSecurity).CurrentValue; }
            catch { position = 0; }

            try {_trader.CancelOrders(security: SelectedSecurity);}
            catch{}

            if (position != 0)
            {            

                    if (position > 0)
                    {
                        orderDirections = OrderDirections.Sell;
                        price = SelectedSecurity.MinPrice;
                    }
                    else
                    {
                        orderDirections = OrderDirections.Buy;
                        price = SelectedSecurity.MaxPrice;
                    }

                    var order = new Order
                    {
                        Trader = _trader,
                        Portfolio = SelectedPortfolio,
                        Security = SelectedSecurity,
                        Direction = orderDirections,
                        Price = price,
                        Volume = Math.Abs(position)
                    };
                    _trader.RegisterOrder(order);
            }
developer_29
developer_29

Здесь, как я понял, ищется данная текущая позиция, а если ни одной нет, то считается, что позиция нулевая (не состоим нигде).

try { position = _trader.Positions.FirstOrDefault(p => p.Security == SelectedSecurity).CurrentValue; }
            catch { position = 0; }

А здесь

try {_trader.CancelOrders(security: SelectedSecurity);}
            catch{}

Закрываются невыполненные заявки или закрываются уже открытые позиции? Или и то, и то?

Если в предыдущем месте закрываются уже открытые позиции, то здесь они опять закрываются, если не закрылись? Или в предыдущем все неисполненные заявки отменяются, а здесь уже открытые позиции закрываются?

            if (position != 0)
            {            

                    if (position > 0)
                    {
                        orderDirections = OrderDirections.Sell;
                        price = SelectedSecurity.MinPrice;
                    }
                    else
                    {
                        orderDirections = OrderDirections.Buy;
                        price = SelectedSecurity.MaxPrice;
                    }

                    var order = new Order
                    {
                        Trader = _trader,
                        Portfolio = SelectedPortfolio,
                        Security = SelectedSecurity,
                        Direction = orderDirections,
                        Price = price,
                        Volume = Math.Abs(position)
                    };
                    _trader.RegisterOrder(order);
            }

Правильно ли я Вас понял?

ra81
ra81

Вообще ранее в стратегиях было TimeCome и на него вешаем что хотим, а не такой хитромудрый способ который поверх ваших стратегий как незнамо что прилеплен. Сейчас может убрали не смотрел сие.

ПС: ну вот esper вам совершенно тоже самое советует. И ведь правильно советует.

MenDel
MenDel Autor

ra81: Вообще ранее в стратегиях было TimeCome и на него вешаем что хотим, а не такой хитромудрый способ который поверх ваших стратегий как незнамо что прилеплен. Сейчас может убрали не смотрел сие.

ПС: ну вот esper вам совершенно тоже самое советует. И ведь правильно советует.

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

ra81
ra81

MenDel:

ra81: Вообще ранее в стратегиях было TimeCome и на него вешаем что хотим, а не такой хитромудрый способ который поверх ваших стратегий как незнамо что прилеплен. Сейчас может убрали не смотрел сие.

ПС: ну вот esper вам совершенно тоже самое советует. И ведь правильно советует.

Так то вы правы, но когда несколько стратегий работает и в этот момент они оказались в противоположных направлениях, зачем каждой из них крыть свои позиции, когда частично они уже покрыты друг об друга. В этой ситуации надо только остатки закрыть. Ну так и пожалуйста, рисуете маленькую стратегию которая просто берет и все позиции кроет в заданное время в ноль по заданному чемодану. А те что торгуют просто вырубаете чуток раньше. Вот и все. Достаточно адекватно получается и без хитрых конструкций. Кода выйдет около 5 строчек в каждой стратегии. Ну и в той что кроет все чуток поболее, но тоже без фанатизма.

MenDel
MenDel Autor

В данном коде я сначала проверяю позицию по моему инструменту(не по всем, а только по нужному). Затем снимаю все активные заявки, также только по моему инструменту А затем если позиция существует, я её закрываю.

developer_29
developer_29
developer_29

MenDel: В данном коде я сначала проверяю позицию по моему инструменту(не по всем, а только по нужному). Затем снимаю все активные заявки, также только по моему инструменту А затем если позиция существует, я её закрываю. Спасибо, что ответили. Хочу задать ещё пару вопросов, если совсем не тяжело, то ответьте, пожалуйста.

1 - при подключении к Quik сразу же возникают 2 портфеля, которые я не создавал. Каким из них пользоваться и если они служат для разных целей, то для каких именно и почему у них такие странные имена?

2 - Как создать заявку, которая просто "сметает" те предолжения, которые сейчас есть, невзирая на их цену (конечно же, они должны начинаться от лучшего к худшему)? Например, когда пишем

var order = this.CreateOrder(direction, Security.GetMarketPrice(direction), Volume);
 
// регистрируем заявку (обычным способом - лимитированной заявкой)
RegisterOrder(order);

, то покупаем по рыночной цене. А как сделать, чтобы просто всё, что есть сметала с прилавка, начиная с лучшего доступного предложения, конечно? Просто выставить цену хуже рыночной, тогда все те, что лучше, точно исполнятся, невзирая на то, что я захотел приобрести по худшей цене?

MenDel
MenDel Autor

Народ подскажите как время точное выставлять на компе. Я думаю вы этим пользуетесь, если не жалко поделитесь кодом😊 А то он чет у меня совсем время криво считает, каждый вечер приходится руками выставлять.

Moadip
Moadip
MenDel
MenDel
MenDel Autor

Moadip: LoggingHelper.SyncMarketTime

Не подскажете почему при синхронизации времени подвисает робот? Точнее подвисает рабочее окно, не проверял как он в этот момент сделки со стаканом получает. И частенько вылетает ошибка, что удаленный компьютер не отвечает, может это этот сервер (time.nist.gov:123) не айс, межет можно еще какие нибудь сервера попробывать?

Ошибка: Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера

VassilSanych
VassilSanych

MenDel: может это этот сервер (time.nist.gov:123) не айс, Это ссылка на рандомный сервер из списка. Да, временами он govnist.

Вот мой код синхронизации:

private int _timeSyncCount = 0; 
		private void SyncTime()
		{
			try
			{
				CustomSyncTime();
			}
			catch (Exception)
			{		
				this.AddErrorLog("Ошибка синхронизации времени");
				ThreadPool.QueueUserWorkItem(_ => RecurciveSyncTime());
			}
		}

		private void CustomSyncTime()
		{
			// уже синхронизировалось
				if (LoggingHelper.NowOffset != TimeSpan.Zero)
					return;
				LoggingHelper.NowOffset = new NtpClient("time.nist.gov:123").GetLocalTime(TimeZoneInfo.Local, 10000).Subtract(DateTime.Now);
				this.AddDebugLog("Время синхронизировано");
		}

		private void RecurciveSyncTime()
		{
			try
			{
				CustomSyncTime();
				return;
			}
			catch
			{
				this.AddErrorLog("Ошибка синхронизации времени");
			}

				// первая треть попыток - раз в 10 секунд  
			if (++_timeSyncCount < Settings.Default.TimeSyncAttempts / 3)
			{
				Thread.Sleep(10000);
					RecurciveSyncTime();
				}
			// вторая треть попыток - раз в 100 секунд  (чуть больше полутора минут)
			else if (_timeSyncCount < 2 * Settings.Default.TimeSyncAttempts / 3)
				{
					Thread.Sleep(100000);
					RecurciveSyncTime();
				}
			// оставшиеся попытки - раз в 1000 секунд   (16.7 минут)
			else if (_timeSyncCount < Settings.Default.TimeSyncAttempts)
				{
					Thread.Sleep(1000000);
					RecurciveSyncTime();
				}
		}
MenDel
MenDel Autor

Это ссылка на рандомный сервер из списка. Да, временами он govnist.

Вот мой код синхронизации:

		private int _timeSyncCount = 0; 
		private void SyncTime()
		{
			try
			{
				// уже синхронизировалось
				if (LoggingHelper.NowOffset != TimeSpan.Zero)
					return;
				LoggingHelper.NowOffset = new NtpClient("time.nist.gov:123").GetLocalTime(TimeZoneInfo.Local, 10000).Subtract(DateTime.Now);
				this.AddDebugLog("Время синхронизировано");
			}
			catch (Exception)
			{		
				this.AddErrorLog("Ошибка синхронизации времени");
				// первая треть попыток - раз в 10 секунд  
				if (++_timeSyncCount < Settings.Default.TimeSyncAttempts / 3)
				ThreadPool.QueueUserWorkItem((x) => 
					{ 
						Thread.Sleep(10000);
						SyncTime();
					});
				// вторая треть попыток - раз в 100 секунд  (чуть больше полутора минут)
				else if (_timeSyncCount < 2 * Settings.Default.TimeSyncAttempts / 3)
					ThreadPool.QueueUserWorkItem((x) =>
					{
						Thread.Sleep(100000);
						SyncTime();
					});
				// оставшиеся попытки - раз в 1000 секунд   (16.7 минут)
				else if (_timeSyncCount < Settings.Default.TimeSyncAttempts)
					ThreadPool.QueueUserWorkItem((x) =>
					{
						Thread.Sleep(1000000);
						SyncTime();
					});
			}
		}

А я ща сделал просто, будет коннектится пока не получит свое, вот

private void TimeSync()
        {
            try
            {                
                LoggingHelper.SyncMarketTime(50);
                this.GuiAsync(() =>
                    {
                        Message("Время синхронизировано");
                    });
            }
            catch { TimeSync(); }
        }

А запускаю его так ```csharp ThreadPool.QueueUserWorkItem(_ => TimeSync());


А можно тупо поставить прогу Absolute Time Corrector, очень удобная, ставишь интервал и она сама часы на компе подводит, хоть каждую секунду.
VassilSanych
VassilSanych

MenDel: А я ща сделал просто, будет коннектится пока не получит свое, вот Так нельзя. Во-первых, если опрашивать чаще, чем раз в 4 секунды, то сервер будет блокировать запросы (так написано у них) во-вторых, если запрашивать в одном потоке, то будет блокироваться основной функционал ради второстепенной информации, в-третьих, от частых сообщений об ошибке засрётся лог, upd в-четвёртых, рекурсия блокирует GC, и при большой рекурсивной вложенности будет переполнение буфера. upd Особенно рекурсия через Exception. А там между прочим каждый раз будет производиться сериализация после рефлекшн. Представляете какого размера будет staсktrace после 20000-й итерации?

MenDel
MenDel Autor

VassilSanych:

MenDel: А я ща сделал просто, будет коннектится пока не получит свое, вот Так нельзя. Во-первых, если опрашивать чаще, чем раз в 4 секунды, то сервер будет блокировать запросы (так написано у них) во-вторых, если запрашивать в одном потоке, то будет блокироваться основной функционал ради второстепенной информации, в-третьих, от частых сообщений об ошибке засрётся лог, upd в-четвёртых, рекурсия блокирует GC, и при большой рекурсивной вложенности будет переполнение буфера. upd Особенно рекурсия через Exception. А там между прочим каждый раз будет производиться сериализация после рефлекшн. Представляете какого размера будет staсktrace после 20000-й итерации?

Если не считать первой причины, я использую другой поток, я не вывожу ошибку в лог, и ты ведь тоже запускаешь повторно метод из catch, я немного не понимаю про рекурсию и GC Может проще прописать в LoggingHelper.SyncMarketTime(5000); 5000 или другое кол-во милисекунд? и тогда не придется усыплять поток и осчитывать итерации и тем более что он сам задает NowOffset. Или я что то недопонимаю.

VassilSanych
VassilSanych

MenDel: Если не считать первой причины, я использую другой поток, каюсь, не обратил внимание на то, что вызов из дополнительного потока. MenDel: я не вывожу ошибку в лог, хммм... довольно опрометчиво. MenDel: и ты ведь тоже запускаешь повторно метод из catch, я немного не понимаю про рекурсию и GC у меня ограниченное количество запусков и большие паузы. GC не отслеживает переменные метода, пока он не завершён, вроде. Но в любом случае при глубокой рекурсии будет переполнение стека на одну только адресацию, а отжирание памяти на сериализацию исключений - это будет бонус :) Не забывай, что в каждом исключении будет нарастающая вложенность. MenDel: Может проще прописать в LoggingHelper.SyncMarketTime(5000); 5000 или другое кол-во милисекунд? на сколько я понимаю, это таймаут, а не пауза MenDel: и тогда не придется усыплять поток и осчитывать итерации и тем более что он сам задает NowOffset. Или я что то недопонимаю. Ставить дополнительный поток на паузу - вещь не накладная. Главное, чтобы слишком много потоков не занимать, но с пулом это вроде тоже не большая проблема. В принципе конечно можно всё в одном дополнительном потоке делать. Просто лень было лишний метод писать :) Идея была в том, что первая попытка выполняется синхронно, а дальше уже в фоне. Кстати методика себя оправдала. Запустил - писало, что ошибка синхронизации. Оставил, пошёл ужинать. Через 2 часа обнаружил, что практически все 2 часа синхронизация не срабатывала и сработала только попытки с 18-й (у меня их всего - 21 была).

Moadip
Moadip

Точнее подвисает рабочее окно Значит вы этот метод вызываете в UI потоке. И пока он не выполнится(по умолчанию 5 сек.), дальше код выполнятся не будет - от этого и подвисает.

может это этот сервер (time.nist.gov:123) не айс, межет можно еще какие нибудь сервера попробывать? Можно синхронизировать хоть по какому серверу, хоть вручную. SyncMarketTime просто выставляет в NowOffset временное смещение.

MenDel
VassilSanych
VassilSanych

Замучила совесть: исправил свой код. Теперь - в одном дополнительном потоке и без вложенных исключений. Саму синхронизацию выделил в отдельный метод. Возможно стоит перебрать сервера из списка http://tf.nist.gov/tf-cgi/servers.cgi , выбрать вручную несколько хороших и выбирать из их списка, не доверяя стандартному адресу. Уж больно он нестабильный. Наверное, большинство серверов перманентно в дауне.

aerv
aerv

Без рекурсии:

        void TimeSync(object state) {
      int count = 0;
      const int maxAttempts = 100;
      while (true) {
        try {
          // Getting time offset
          // Logging
          break;
        } catch {
          count++;
          // Logging
        }
        if (count >= maxAttempts)
          break;
        Thread.Sleep((int) (1000*(3 + Math.Exp(count/5.0))));  // Рассчитывать задержку можно как угодно
      }
      ((ManualResetEvent) state).Set();
    }

    [TestMethod]
    public void TimeCorrectTest() {
      var ev = new ManualResetEvent(false);
      ThreadPool.QueueUserWorkItem( TimeSync, ev );
      ev.WaitOne(); // Блокировка - для теста
    }


Кстати, для синхронизации времени вполне достаточно настроить штатную службу времени в Windows. параметры реестра сервера пул серверов Это для общего понимания

VassilSanych
VassilSanych

aerv: А зачем рекурсия-то? Можно и так. Правда блокировать торговый функционал, пока не будет успешной синхронизации часов, - это, повторюсь, не комильфо.

aerv: Кстати, для синхронизации времени вполне достаточно настроить штатную службу времени в Windows. параметры реестра Там есть небольшая сносочка с предупреждением. По смыслу - "осторожно! мы сами этой хрени не доверяем".

MenDel
MenDel Autor

Да кстати можно ещ добавить проверку инета, а то вдруг его отрубят а он будет все пытвться время узнать.

Так ведь никакой рекурсии не будет?

ThreadPool.QueueUserWorkItem(_ => TimeSync());

private void TimeSync()
        {
            IPStatus status = IPStatus.Unknown;
            try
            {
                PingReply pr = new Ping().Send(@"google.ru");
                status = pr.Status;
            }
            catch { }

            if (status == IPStatus.Success)
            {
                int i = 0;
                while(true)
                {
                    i++;
                    try
                    {
                        LoggingHelper.SyncMarketTime(50);
                        this.GuiAsync(() => Message("Время синхронизировано"));
                        break;
                    }
                    catch
                    {
                        if (i%10 == 0)
                        {
                            PingReply pr = new Ping().Send(@"google.ru");
                            status = pr.Status;
                        }
                        if (status != IPStatus.Success) break;
                        if (i <= 10) Thread.Sleep(1000);
                        else if (i > 10 && i <= 50) Thread.Sleep(10000);
                        else if (i > 50) Thread.Sleep(60000);
                    }
                }
            }
        }
aerv
aerv

VassilSanych:

aerv: Кстати, для синхронизации времени вполне достаточно настроить штатную службу времени в Windows. параметры реестра Там есть небольшая сносочка с предупреждением. По смыслу - "осторожно! мы сами этой хрени не доверяем". Ну, у меня много месяцев она работает так как надо. Разумеется, я никому ничего не навязываю. )

MenDel: Да кстати можно ещ добавить проверку инета, а то вдруг его отрубят а он будет все пытвться время узнать. Так ведь никакой рекурсии не будет? А смысл всего этого? Если инет есть, то и по NTP ответ придет. Если инета нет, то и сделать ничего нельзя.

VassilSanych
VassilSanych

Для России хороши сервера 0.ru.pool.ntp.org 1.ru.pool.ntp.org 2.ru.pool.ntp.org 3.ru.pool.ntp.org Они во-первых работают, а во-вторых пинг до них в 4-10 раз меньше, чем до серверов Пиндостана.

VassilSanych
VassilSanych

Безотносительно к трейдингу Синхронизация часов в Windows

w32tm /config /syncfromflags:manual /manualpeerlist:0.ru.pool.ntp.org,1.ru.pool.ntp.org,2.ru.pool.ntp.org,3.ru.pool.ntp.org /update
w32tm /resync
w32tm /query /status

При запущенном сервисе времени и достаточно небольшом смещении времени (не годы).

aerv
aerv

VassilSanych: Безотносительно к трейдингу w32tm /monitor /computers:0.ru.pool.ntp.org Покажет смещение времени на сервере относительно локального времени: Кстати, вместо DNS имен можно указывать IP адреса. Это снимает риски отказа DNS серверов.

VassilSanych
VassilSanych

aerv: Это снимает риски отказа DNS серверов. Но добавляет риски неожиданной смены IP