Alexander
|
Дата: 06.01.2012
как понимаете что не вызывается обработчик? а сделки-то у MQS проходят?
|
|
|
|
ak
|
Дата: 06.01.2012
Alexander Mukhanchikov  как понимаете что не вызывается обработчик? В хронологическом порядке как обнаруживал проблему: - Не создаются защитные стратегии для совершенных сделок
- Breakpoint на первой строчке внутри цикла foreach (MyTrade trade in trades) не срабатывает при отладке
- Тестовое сообщение в лог, вставленное первой строчкой в метод ProtectMyNewTrades, не появляется в логе
Alexander Mukhanchikov  а сделки-то у MQS проходят? Да. Более того, событие ITrader.NewMyTrades вызывается нормально, подписавшись на него, я, например, нормально заполняю TradeGrid новыми сделками.
|
Автор топика
|
|
|
Alexander
|
Дата: 09.01.2012
Дело в том, что порой стратегия MQS может завершится раньше чем придёт событие о новой сделки (NewMyTrades) Что у вас и происходит.
Есть 2 выхода: 1) Поставить флаг RemoveChildStrategies у дочерней стратегии в false - тогда стратегия MQS после завершения не будет удаляться и события должны придти; 2) Реагировать не на событие новых сделок, а на событие изменения отправленного ордера.
P.S. Доступ на codeplex даём тем, кто готов вносить изменения в исходный код, выложенный там.
|
|
|
|
ak
|
Дата: 10.01.2012
|
|
|
|
Большое спасибо за ответ, Александр. Сразу возникает вопрос, не видите ли вы способа внутри MQS синхронизировать генерацию события NewMyTrade и смены ProcessState стратегии (и генерации ProcessStateChanged соответственно), чтобы событие нового трейда гарантированно файрилось до того, как стратегия отрапортует о своем завершении? Сложно что-то предполагать не видя реализации, но судя по всему метод генерирующий NewMyTrade (что-нибудь вроде OnNewMyTrade) слишком долго ждет какого-то ресурса (шлюза ITrader, например, пока другие события успешно генерируются), может его можно пересмотреть? Или, например, заставить Strategy.DisposeManaged() (если именно этот метод вызывается для уничтожения родительской стратегии - дочерней) как-то подождать завершения генерации всех событий. И еще небольшой вопрос, я не совсем понял второе решение: Quote:Реагировать не на событие новых сделок, а на событие изменения отправленного ордера. Вы имеете ввиду order переданный в конструктор MQS? Так ведь он не имеет ничего общего с ордером, который будет на самом деле создан и исполнен в ходе котирования. Например этот анонимный метод никогда не будет вызван: Code
this.
When(order.Changed())
.Do(() => {
int i = 1;
});
Или я неправильно вас понял?
|
Автор топика
|
|
|
Alexander
|
Дата: 10.01.2012
Нет, внутрях MQS не будет ничего меняться. События из QuikTrader, да и из любого трейдера не синхронны - нам событие о новой сделке может придти до \ после события о новом ордере.
У MQS есть событие NewOrders для этих новых ордеров можно создавать любые правила которые угодны
И да, вариант с RemoveChildStrategies намного проще.
|
|
|
|
ak
|
Дата: 10.01.2012
Quote:И да, вариант с RemoveChildStrategies намного проще. Безусловно, но подобные сообщения в логе напрягают: Quote:SLS | 05.01.2012 20:40:30.000 | Внимание | Котирование в состоянии Stopped. Все же не очень понятно. Quote:События из QuikTrader, да и из любого трейдера не синхронны - нам событие о новой сделке может придти до \ после события о новом ордере. Какое условие уничтожения дочерней стратегии/изменения MQS.ProcessState на Stopped? Приход в MQS стратегию события от ITrader о новой сделке (в самом простом случае), так? Так почему же MQS.NewMyTrade не появляется мгновенно после этого и только потом в том же потоке не происходит изменение ProcessState на Stopped и генерация ProcessStateChanged? Как тут вообще может возникнуть состояние гонок?
|
Автор топика
|
|
|
ak
|
Дата: 10.01.2012
Alexander Mukhanchikov  У MQS есть событие NewOrders для этих новых ордеров можно создавать любые правила которые угодны Спасибо, понял. Но если событие MQS.NewMyTrades может не успеть выполниться до уничтожения объекта стратегии, где гарантия, что события на порожденные ею orders успеют выполниться? Или эти orders никак не затрагиваются при dispose стратегии?
|
Автор топика
|
|
|
Alexander
|
Дата: 10.01.2012
|
|
|
|
Quote:Какое условие уничтожения дочерней стратегии/изменения MQS.ProcessState на Stopped? Приход в MQS стратегию события от ITrader о новой сделке (в самом простом случае), так? Так почему же MQS.NewMyTrade не появляется мгновенно после этого и только потом в том же потоке не происходит изменение ProcessState на Stopped и генерация ProcessStateChanged? Как тут вообще может возникнуть состояние гонок? Нет, не так. MQS останавливается следующим образом: - у стратегии меняется позиция (по заявкам(!), не по сделкам). По умолчанию мониторим изменение позиции стратегии именно по ордерам, а не сделкам. - проверяется условие можем ли окончить - если да - заканчиваем либо - по TimeOut. Т.к. не так - остальное рассуждение не требует ответа. Quote:Спасибо, понял. Но если событие MQS.NewMyTrades может не успеть выполниться до уничтожения объекта стратегии, где гарантия, что события на порожденные ею orders успеют выполниться? Или эти orders никак не затрагиваются при dispose стратегии? Стратегия останавливается либо по таймауту, либо по позиции. Позиция меняется по ордерам. Следовательно ордеры придут.
|
|
|
|
ak
|
Дата: 10.01.2012
Спасибо, теперь стало все гораздо яснее. Первичность ордеров перед сделками в принятии решения на остановку было ключевым моментом.
|
Автор топика
|
|
|
risty
|
Дата: 12.01.2012
|
|
|
|
Думаю мой вопрос примерно в эту тему. Заранее прошу сильно не ругаться т.к. только начинаю осваивать C# и S# (4.0.14.0) Есть некая событийная стратегия FirstStrategy. По замыслу она должна торговать не более чем одним контрактом(RIH2) Code
private int CurrentPosition;
public FirstStrategy()
{
this.RemoveChildStrategies = false;
this.CurrentPosition = 0;
}
protected override void OnStarting()
{
this
.When(base.Security.SecurityNewTrades())
.Do(base.PositionManager.Init)
.Once();
this
.When(base.Security.SecurityNewTrades())
.Do(UpOrDown);
this
.When(this.Stopping())
.ClosePosition();
base.OnStarting();
}
private void UpOrDown()
{
// если наша стратегия в процессе остановки
if (ProcessState == ProcessStates.Stopping)
{
// отменяем активные заявки
CancelActiveOrders();
return;
}
//свежие сделки ?
if ((base.Security.LastTrade != null) && ((base.Trader.MarketTime - base.Security.LastTrade.Time).Duration() > new TimeSpan(0, 0, 5))) return;
if ((base.Security.LastTrade.Price != 0) && (this.LevelUP != null) && (this.LevelDown != null))
{
//UpMoving
if ((new Unit(base.Security.LastTrade.Price)) > this.LevelUP)
{
if ((this.CurrentPosition == 0) | (this.CurrentPosition == -1))
{
_orderDirection = OrderDirections.Buy;
var order = this.CreateOrder(_orderDirection, Security.GetMarketPrice(_orderDirection), Volume);
CurrentPosition++;
var strategyUp = new MarketQuotingStrategy(order, new Unit(0), new Unit(0));
ChildStrategies.Add(strategyUp);
return;
}
}
//DownMoving
if ((new Unit(base.Security.LastTrade.Price)) < this.LevelDown)
{
if ((this.CurrentPosition == 0) | (this.CurrentPosition == 1))
{
_orderDirection = OrderDirections.Sell;
var order = this.CreateOrder(_orderDirection, Security.GetMarketPrice(_orderDirection), Volume);
CurrentPosition--;
var strategyDown = new MarketQuotingStrategy(order, new Unit(0), new Unit(0));
ChildStrategies.Add(strategyDown);
return;
}
}
}
}
В связи с тем, что this.PositionManager.Position основной стратегии запаздывает относительно Котировния, для учета позиции использую this.CurrentPosition. При тестировании SampleHistoryTesting поля CurrentPosition и this.PositionManager.Position ведут себя изменяются в диапазоне -1,0,1, что и требуется. А при тестировании SampleRealTimeTesting this.PositionManager.Position вылетает далеко за рамки одного контракта. В связи с этим вопрос - как правильно учитывать позицию основной стратегии в тестах и в бою?
|
|
|
|
ak
|
Дата: 12.01.2012
Гораздо, но не полностью, к сожалению. Александр, подскажите пожалуйста, почему подобная конструкция также не работает с QuikTrader'ом: Code
this
.When(marketQuotingStrategy.StrategyNewOrder())
.Do((qOrder) =>
{
this
.When(qOrder.NewTrades())
.Do(ProtectMyNewTrades)
.Periodical(() => qOrder.IsMatched());
});
Симптомы те же: ProtectMyNewTrades вызывается в RealTimeEmulationTrader и не вызывается в QuikTrader. Как же правильно защитить сделки после котирования?
|
Автор топика
|
|
|
Alexander
|
Дата: 12.01.2012
Ни разу не вызывается?
Подпишитесь на Trader.NewMyTrades и посмотрите приходят ли там сделки, равные qOrder.
|
|
|
|
ak
|
Дата: 12.01.2012
|
|
|
|
Alexander Mukhanchikov  Ни разу не вызывается?
Подпишитесь на Trader.NewMyTrades и посмотрите приходят ли там сделки, равные qOrder. Прошу игнорировать последний мой вопрос, приведенная выше конструкция работает стабильно (насколько мне удалось потестировать) с QuikTrader'ом (при RemoveChildStrategies == true). Проблема, мешавшая вызываться обработчику, заключалась в том, что поток прерывался Exception'ом в другом обработчике (в логи, к сожалению, ничего не попадало): Code
...
_strategy.NewMyTrades += OnNewTrades;
...
private void OnNewTrades(IEnumerable<MyTrade> trades)
{
TradesGrid.Trades.AddRange(trades);
var newTradeLogMessage = "I've {0} {1} future contracts at {2}";
trades.ForEach(t => this._log.AddLog(
new ExtendedLogMessage(this._log, DateTime.Now, ErrorTypes.Warning, ExtendedLogMessage.ImportanceLevel.High,
newTradeLogMessage,
(t.Trade.OrderDirection.Value == OrderDirections.Buy) ? "bought" : "sold",
t.Trade.Volume,
t.Trade.Price)));
}
t.Trade.OrderDirection есть Nullable enum и в нем регулярно был null вместо значения, чего я не ожидал (хотя должен был). Александр, подскажите, почему в сформированном trade OrderDirection может быть null (все остальные поля объекта были заполнены верными значениями)? И самое интересное TradeGrid подобные трейды отображал нормально, с верным направлением - что необходимо вызвать дополнительно чтобы OrderDirection заполнился верным значением?
|
Автор топика
|
|
|
Alexander
|
Дата: 12.01.2012
Поставьте бряку в начало функции, посмотрите - есть ли там OrderDirection у сделок в пришедшем массиве
|
|
|
|
ak
|
Дата: 12.01.2012
Alexander Mukhanchikov  Поставьте бряку в начало функции, посмотрите - есть ли там OrderDirection у сделок в пришедшем массиве Вот как интересно: Code
((StockSharp.BusinessEntities.MyTrade[])(trades))[0].Trade.OrderDirection = null
((StockSharp.BusinessEntities.MyTrade[])(trades))[0].Order.Direction = Buy
|
Автор топика
|
|
|
Alexander
|
Дата: 12.01.2012
ak  Alexander Mukhanchikov  Поставьте бряку в начало функции, посмотрите - есть ли там OrderDirection у сделок в пришедшем массиве Вот как интересно: Code
((StockSharp.BusinessEntities.MyTrade[])(trades))[0].Trade.OrderDirection = null
((StockSharp.BusinessEntities.MyTrade[])(trades))[0].Order.Direction = Buy
Ничего интересного вроде нет у order направление есть всегда у сделки оно может отсутствовать если шлюз эту информацию не транслирует. смартком - не транслирует. (плаза - тоже не транслирует. квик - проставляет)
|
|
|
|
ak
|
Дата: 12.01.2012
OK, спасибо! Это очевидно, когда знаешь и видишь как заполняется объект, тут же, когда не видишь исходного кода, - просто ожидаешь наиболее очевидного варианта. Здесь я думал, что значение, в случае не передачи шлюзом, просто копируется из породившего сделку order'а. Спасибо за ваше время, ответы и ваш труд над S#.
|
Автор топика
|
|
|
Alexander
|
Дата: 12.01.2012
Нет, документация как раз тоже не говорит о том что что-то куда-то копируется. У нас для ордера на Sell легко могут проходить как Buy, так и Sell сделки.
Хотя, наверное, можно было понять двояко.
|
|
|