VassilSanych
|
Дата: 18.12.2012
Сергей MenDel  Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи. Да вы, батенька, экстремал. Вы уверены, что вас исполнят в последние 5 секунд?
|
|
|
|
Sergey Masyura
|
Дата: 18.12.2012
Сергей MenDel  Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи. Если без привязки в закрытому коду, то, например, Time scheduler in C#, By Aleksey Bykov, 16 May 2007. http://www.codeproject.c...8633/Time-scheduler-in-C
|
|
|
|
MenDel
|
Дата: 18.12.2012
VassilSanych  Сергей MenDel  Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи. Да вы, батенька, экстремал. Вы уверены, что вас исполнят в последние 5 секунд? Я ща так руками закрываюсь, единственное приходится сверять часы на компе каждый день
|
Автор топика
|
|
|
MenDel
|
Дата: 18.12.2012
Sergey Masyura  Сергей MenDel  Всем привет, подскажите как сделать событие которое будет срабатывать за 5 секунд до закрытия вечерней сессии? Ориентируясь на время биржи. Если без привязки в закрытому коду, то, например, Time scheduler in C#, By Aleksey Bykov, 16 May 2007. https://www.codeproject.c...8633/Time-scheduler-in-C спс, ща посмотрим. Я ваще думал это в S# реализовано, вещь то нужная.
|
Автор топика
|
|
|
esper
|
Дата: 18.12.2012
Часы в любом случае сверять придется. В S# можно попробовать посмотреть такую штуку.
|
|
|
|
MenDel
|
Дата: 15.01.2013
Нашел, решил написать мож кому пригодится ещ И часы сверять не надо Code
_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
|
Дата: 15.01.2013
Сергей MenDel  Code
_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);
});
это конечно хорошо, но в настоящий момент GetMarketTime используется DateTime.Now, которое просто сдвинуто на часовой пояс указанной биржи.
|
|
|
|
developer_29
|
Дата: 21.01.2013
Quote:Code
_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);
});
А напишите, пожалуйста, код метода Button_ClosePosition_Click. первые 2 строчки нужны для того, чтобы получать данные каждую секунду?
|
|
|
|
MenDel
|
Дата: 21.01.2013
developer_29  А напишите, пожалуйста, код метода Button_ClosePosition_Click. первые 2 строчки нужны для того, чтобы получать данные каждую секунду?
Первая строчка - чтоб каждую секунду, а вторая вызывает каждый раз метод Если по рынку закрывать, то делаю так Code
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);
}
|
Автор топика
|
|
|
ra81
|
Дата: 22.01.2013
Вообще ранее в стратегиях было TimeCome и на него вешаем что хотим, а не такой хитромудрый способ который поверх ваших стратегий как незнамо что прилеплен. Сейчас может убрали не смотрел сие.
ПС: ну вот esper вам совершенно тоже самое советует. И ведь правильно советует.
|
|
|
|
MenDel
|
Дата: 22.01.2013
ra81  Вообще ранее в стратегиях было TimeCome и на него вешаем что хотим, а не такой хитромудрый способ который поверх ваших стратегий как незнамо что прилеплен. Сейчас может убрали не смотрел сие.
ПС: ну вот esper вам совершенно тоже самое советует. И ведь правильно советует. Так то вы правы, но когда несколько стратегий работает и в этот момент они оказались в противоположных направлениях, зачем каждой из них крыть свои позиции, когда частично они уже покрыты друг об друга. В этой ситуации надо только остатки закрыть.
|
Автор топика
|
|
|
developer_29
|
Дата: 23.01.2013
|
|
|
|
Здесь, как я понял, ищется данная текущая позиция, а если ни одной нет, то считается, что позиция нулевая (не состоим нигде). Code
try { position = _trader.Positions.FirstOrDefault(p => p.Security == SelectedSecurity).CurrentValue; }
catch { position = 0; }
А здесь Code
try {_trader.CancelOrders(security: SelectedSecurity);}
catch{}
Закрываются невыполненные заявки или закрываются уже открытые позиции? Или и то, и то? Если в предыдущем месте закрываются уже открытые позиции, то здесь они опять закрываются, если не закрылись? Или в предыдущем все неисполненные заявки отменяются, а здесь уже открытые позиции закрываются? Code
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);
}
Правильно ли я Вас понял?
|
|
|
|
MenDel
|
Дата: 23.01.2013
В данном коде я сначала проверяю позицию по моему инструменту(не по всем, а только по нужному). Затем снимаю все активные заявки, также только по моему инструменту А затем если позиция существует, я её закрываю.
|
Автор топика
|
|
|
developer_29
|
Дата: 25.01.2013
|
|
|
|
MenDel  В данном коде я сначала проверяю позицию по моему инструменту(не по всем, а только по нужному). Затем снимаю все активные заявки, также только по моему инструменту А затем если позиция существует, я её закрываю. Спасибо, что ответили. Хочу задать ещё пару вопросов, если совсем не тяжело, то ответьте, пожалуйста. 1 - при подключении к Quik сразу же возникают 2 портфеля, которые я не создавал. Каким из них пользоваться и если они служат для разных целей, то для каких именно и почему у них такие странные имена? 2 - Как создать заявку, которая просто "сметает" те предолжения, которые сейчас есть, невзирая на их цену (конечно же, они должны начинаться от лучшего к худшему)? Например, когда пишем Code
var order = this.CreateOrder(direction, Security.GetMarketPrice(direction), Volume);
// регистрируем заявку (обычным способом - лимитированной заявкой)
RegisterOrder(order);
, то покупаем по рыночной цене. А как сделать, чтобы просто всё, что есть сметала с прилавка, начиная с лучшего доступного предложения, конечно? Просто выставить цену хуже рыночной, тогда все те, что лучше, точно исполнятся, невзирая на то, что я захотел приобрести по худшей цене?
|
|
|
|
esper
|
Дата: 25.01.2013
|
|
|
|
ra81
|
Дата: 27.01.2013
MenDel  ra81  Вообще ранее в стратегиях было TimeCome и на него вешаем что хотим, а не такой хитромудрый способ который поверх ваших стратегий как незнамо что прилеплен. Сейчас может убрали не смотрел сие.
ПС: ну вот esper вам совершенно тоже самое советует. И ведь правильно советует. Так то вы правы, но когда несколько стратегий работает и в этот момент они оказались в противоположных направлениях, зачем каждой из них крыть свои позиции, когда частично они уже покрыты друг об друга. В этой ситуации надо только остатки закрыть. Ну так и пожалуйста, рисуете маленькую стратегию которая просто берет и все позиции кроет в заданное время в ноль по заданному чемодану. А те что торгуют просто вырубаете чуток раньше. Вот и все. Достаточно адекватно получается и без хитрых конструкций. Кода выйдет около 5 строчек в каждой стратегии. Ну и в той что кроет все чуток поболее, но тоже без фанатизма.
|
|
|
|
MenDel
|
Дата: 29.01.2013
Народ подскажите как время точное выставлять на компе. Я думаю вы этим пользуетесь, если не жалко поделитесь кодом А то он чет у меня совсем время криво считает, каждый вечер приходится руками выставлять.
|
Автор топика
|
|
|
Moadip
|
Дата: 29.01.2013
|
|
|
|
MenDel
|
Дата: 30.01.2013
Moadip  Не подскажете почему при синхронизации времени подвисает робот? Точнее подвисает рабочее окно, не проверял как он в этот момент сделки со стаканом получает. И частенько вылетает ошибка, что удаленный компьютер не отвечает, может это этот сервер (time.nist.gov:123) не айс, межет можно еще какие нибудь сервера попробывать? Ошибка: Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера
|
Автор топика
|
|
|
Moadip
|
Дата: 30.01.2013
Quote:Точнее подвисает рабочее окно Значит вы этот метод вызываете в UI потоке. И пока он не выполнится(по умолчанию 5 сек.), дальше код выполнятся не будет - от этого и подвисает. Quote:может это этот сервер (time.nist.gov:123) не айс, межет можно еще какие нибудь сервера попробывать?
Можно синхронизировать хоть по какому серверу, хоть вручную. SyncMarketTime просто выставляет в NowOffset временное смещение.
|
|
|
|
VassilSanych
|
Дата: 01.02.2013
|
|
|
|
MenDel  может это этот сервер (time.nist.gov:123) не айс, Это ссылка на рандомный сервер из списка. Да, временами он govnist. Вот мой код синхронизации: Code
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
|
Дата: 01.02.2013
|
|
|
|
Quote:Это ссылка на рандомный сервер из списка. Да, временами он govnist. Вот мой код синхронизации: Code
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();
});
}
}
А я ща сделал просто, будет коннектится пока не получит свое, вот Code
private void TimeSync()
{
try
{
LoggingHelper.SyncMarketTime(50);
this.GuiAsync(() =>
{
Message("Время синхронизировано");
});
}
catch { TimeSync(); }
}
А запускаю его так Code
ThreadPool.QueueUserWorkItem(_ => TimeSync());
А можно тупо поставить прогу Absolute Time Corrector, очень удобная, ставишь интервал и она сама часы на компе подводит, хоть каждую секунду.
|
Автор топика
|
|
|
VassilSanych
|
Дата: 01.02.2013
MenDel  А я ща сделал просто, будет коннектится пока не получит свое, вот Так нельзя. Во-первых, если опрашивать чаще, чем раз в 4 секунды, то сервер будет блокировать запросы (так написано у них) во-вторых, если запрашивать в одном потоке, то будет блокироваться основной функционал ради второстепенной информации, в-третьих, от частых сообщений об ошибке засрётся лог, upd в-четвёртых, рекурсия блокирует GC, и при большой рекурсивной вложенности будет переполнение буфера. upd Особенно рекурсия через Exception. А там между прочим каждый раз будет производиться сериализация после рефлекшн. Представляете какого размера будет staсktrace после 20000-й итерации?
|
|
|
|
MenDel
|
Дата: 01.02.2013
|
|
|
|
VassilSanych  MenDel  А я ща сделал просто, будет коннектится пока не получит свое, вот Так нельзя. Во-первых, если опрашивать чаще, чем раз в 4 секунды, то сервер будет блокировать запросы (так написано у них) во-вторых, если запрашивать в одном потоке, то будет блокироваться основной функционал ради второстепенной информации, в-третьих, от частых сообщений об ошибке засрётся лог, upd в-четвёртых, рекурсия блокирует GC, и при большой рекурсивной вложенности будет переполнение буфера. upd Особенно рекурсия через Exception. А там между прочим каждый раз будет производиться сериализация после рефлекшн. Представляете какого размера будет staсktrace после 20000-й итерации? Если не считать первой причины, я использую другой поток, я не вывожу ошибку в лог, и ты ведь тоже запускаешь повторно метод из catch, я немного не понимаю про рекурсию и GC Может проще прописать в LoggingHelper.SyncMarketTime(5000); 5000 или другое кол-во милисекунд? и тогда не придется усыплять поток и осчитывать итерации и тем более что он сам задает NowOffset. Или я что то недопонимаю.
|
Автор топика
|
|
|
VassilSanych
|
Дата: 01.02.2013
|
|
|
|
MenDel  Если не считать первой причины, я использую другой поток,
каюсь, не обратил внимание на то, что вызов из дополнительного потока. MenDel  я не вывожу ошибку в лог,
хммм... довольно опрометчиво. MenDel  и ты ведь тоже запускаешь повторно метод из catch, я немного не понимаю про рекурсию и GC
у меня ограниченное количество запусков и большие паузы. GC не отслеживает переменные метода, пока он не завершён, вроде. Но в любом случае при глубокой рекурсии будет переполнение стека на одну только адресацию, а отжирание памяти на сериализацию исключений - это будет бонус :) Не забывай, что в каждом исключении будет нарастающая вложенность. MenDel  Может проще прописать в LoggingHelper.SyncMarketTime(5000); 5000 или другое кол-во милисекунд?
на сколько я понимаю, это таймаут, а не пауза MenDel  и тогда не придется усыплять поток и осчитывать итерации и тем более что он сам задает NowOffset. Или я что то недопонимаю.
Ставить дополнительный поток на паузу - вещь не накладная. Главное, чтобы слишком много потоков не занимать, но с пулом это вроде тоже не большая проблема. В принципе конечно можно всё в одном дополнительном потоке делать. Просто лень было лишний метод писать :) Идея была в том, что первая попытка выполняется синхронно, а дальше уже в фоне. Кстати методика себя оправдала. Запустил - писало, что ошибка синхронизации. Оставил, пошёл ужинать. Через 2 часа обнаружил, что практически все 2 часа синхронизация не срабатывала и сработала только попытки с 18-й (у меня их всего - 21 была).
|
|
|