← Voltar

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

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

Este tópico foi útil?

Compartilhar tópico

Comentários (34)

Entrar ou Criar conta, Faça login ou cadastre-se para deixar um comentário

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