Сергей Гаврилов, [15.01.15 12:15]
2:55:01 PM
Sergey Dvortsov
Александр Спирин, [15.01.15 12:17]
Приветствую! Не получается в методе MainAlgorithm стратегии определить, последняя пришла свечка из серии или нет - вызовы не компилируются:
Александр Спирин, [15.01.15 12:17]
var timeFrame = (TimeSpan)_series.Arg; - это нормально,
Александр Спирин, [15.01.15 12:18]
а следующий - var time = timeFrame.GetCandleBounds(_series.Security).Min - timeFrame; - получаю ошибки компилятора:
Error 2 Argument 2: cannot convert from 'StockSharp.BusinessEntities.Security' to 'System.DateTime' C:\Users\Александр\Documents\Visual Studio 2012\Projects\My\SampleSmartSMA\SuhovBandsStrategy.cs 95 50 SampleSmartSMA
и
Error 1 'System.TimeSpan' does not contain a definition for 'GetCandleBounds' and the best extension method overload 'StockSharp.Algo.Candles.CandleHelper.GetCandleBounds(System.TimeSpan, System.DateTime)' has some invalid arguments C:\Users\Александр\Documents\Visual Studio 2012\Projects\My\SampleSmartSMA\SuhovBandsStrategy.cs 95 24 SampleSmartSMA
Что я делаю не так?
Сергей Гаврилов, [15.01.15 12:20]
для работы с разными таймфремами нужно создать для каждого таймфрейма свою CandleSeries.. Каждая серия запускается отдельно при помощи метода CandleManager.Start. Обработать серии можно или в отдельных событиях Series.ProcessCandle или в candlemanager.Processing.
2:57:44 PM
_series = new CandleSeries(typeof(TimeFrameCandle), _lkoh, TimeSpan.FromMinutes(1));
_series5 = new CandleSeries(typeof(TimeFrameCandle), _lkoh, TimeSpan.FromMinutes(5));
_series.ProcessCandle += candle =>
{
Console.WriteLine("минутка");
};
_series5.ProcessCandle += candle =>
{
Console.WriteLine("пятиминутка");
};
_candlemanager.Processing += (series, candle) =>
{
if ((TimeSpan)candle.Arg == TimeSpan.FromMinutes(1))
{ Console.WriteLine("минутка"); }
if ((TimeSpan)candle.Arg == TimeSpan.FromMinutes(5))
{ Console.WriteLine("пятиминутка"); }
};
_candlemanager.Start(_series);
_candlemanager.Start(_series5);
Александр Спирин, [15.01.15 12:22]
понял, попробую.
Сергей Гаврилов, [15.01.15 12:35]
Метод TimeFrame.GetCandleBounds(Security) больше не используется, нужно использовать одну из новых перегрузок
// TimeFrame.GetCandleBounds(DateTime), TimeFrame.GetCandleBounds(DateTime, ExchangeBoard), TimeFrame.GetCandleBounds(DateTime, WorkingTime)
Сергей Гаврилов, [15.01.15 12:36]
var candleBounds = timeFrame.GetCandleBounds(Trader.GetMarketTime(_candleSeries.Security));
Александр Спирин, [15.01.15 12:37]
Компилятор не понимает, что такое Trader - я в методе стратегии нахожусь...
Сергей Гаврилов, [15.01.15 12:38]
Это пример..
Александр Спирин, [15.01.15 12:38]
а по-другому я DateTime могу получить?
Сергей Гаврилов, [15.01.15 12:38]
текущую дату вставь и все
Александр Спирин, [15.01.15 12:42]
так работает, но что будет, если у меня на рабочей станции время разойдётся с торговой площадкой?
Сергей Гаврилов, [15.01.15 12:43]
тогда из коннектора время получай, как я показал
Сергей Гаврилов, [15.01.15 12:44]
var time = timeFrame.GetCandleBounds(Connector.GetMarketTime(Security)).Min - timeFrame; //находим время предпоследней свечк
Александр Спирин, [15.01.15 12:45]
спасибо, так работает.
Александр Спирин, [15.01.15 12:54]
Сергей, а как реализовать скользящий стоп-лосс? Из уроков я вынес, что для этого нужно использовать дочернюю стратегию stoploss, но где-то говорилось, что при изменении уровня цены её надо останавливать и перезапускать с новой ценой - вот это как делается?
Александр Спирин, [15.01.15 12:54]
Моежт в примерах это есть?
Сергей Гаврилов, [15.01.15 12:55]
Нет в примерах нет..
Сергей Гаврилов, [15.01.15 12:59]
Если коротко, то в родительской стратегии создаете правило на повление новых сделок.. В этом правиле при появлении новых условий удаляете StopLoss из дочерних стратегий и добавляете новую с новй ценой..
Александр Спирин, [15.01.15 13:02]
Почти понятно, но как удалить StopLoss из дочерних стратегий (её ещё и остановить надо, наверное?)
Сергей Гаврилов, [15.01.15 13:03]
да. сначала остановить надо..
Сергей Гаврилов, [15.01.15 13:04]
Стратегию удалить или заявку?
Александр Спирин, [15.01.15 13:06]
Ммм... какую заявку? - StopLoss же стоп-заявок не ставит, не правда ли? Вы написали: "...удаляете StopLoss из дочерних стратегий..." - да, так как её удалить? и как её остановить перед удалением?
Сергей Гаврилов, [15.01.15 13:07]
ChaildStrategies.Remove(Strategy)
Александр Спирин, [15.01.15 13:07]
А остановить как?
Сергей Гаврилов, [15.01.15 13:21]
Strategy.Stop
Сергей Гаврилов, [15.01.15 13:23]
Это на всякий случай, скорее всего стратегия автоматически останавливается при удалении..
Сергей Гаврилов, [15.01.15 13:24]
Посмотрите пример про арбитражную стратегию... Там показано как добавляют/удаляют дочерние стратегии..
Александр Спирин, [15.01.15 16:18]
Я не нашёл в примере остановку для стратегии через Stop() - там такой вызов:ChildStrategies.Any(f => f is FastOrderStrategy && ((FastOrderStrategy) f).StrategySignal == FastStrategySignals.Exit);
- он останавливает дочернюю стратегию?
Сергей Гаврилов, [15.01.15 16:19]
Там показано, как их добавлять и удалять..
Александр Спирин, [15.01.15 16:20]
Я смотрю на файл ArbitrageStrategy.cs из 6-го примера - это то, о чём Вы говорите?
Сергей Гаврилов, [15.01.15 16:22]
но из этой или другой похожей конструкции Вы можете вернуть стратегию и вызвать метод Stop
Александр Спирин, [15.01.15 16:27]
что-то такое?
var sls = (StopLossStrategy)ChildStrategies.FirstOrDefault(s => s is StopLossStrategy);
if( sls != null )
sls.Stop();
Сергей Гаврилов, [15.01.15 16:28]
Или так или прямо в этой конструкции стоп
Александр Спирин, [15.01.15 16:33]
А как Stop вызвать из эой конструкции? - код ChildStrategies.FirstOrDefault(s => s is StopLossStrategy && s.Stop()); не пропускает компилятор (не могу, говорит, оператор && применить к bool и void)
Сергей Гаврилов, [15.01.15 16:36]
Там еще одну лямбду надо вставить..
Сергей Гаврилов, [15.01.15 16:49]
ChildStrategies.FirstOrDefault(f => f is FastOrderStrategy).Stop();
Сергей Гаврилов, [15.01.15 16:49]
С лямбдой я погорячился..
Александр Спирин, [15.01.15 16:50]
Спасибо.
Сергей Гаврилов, [15.01.15 16:50]
Но
Сергей Гаврилов, [15.01.15 16:52]
Но, возможно, что это лишняя операция.. Скорее всего она сама останавливается, когда мы ее удаляем..
Сергей Гаврилов, [15.01.15 17:00]
Вот такое правило для для дочерней стратегии сделай Strategy.WhenStopped() и посмотри возникает это событие после удаления без явной остановки или нет..
Александр Спирин, [15.01.15 17:02]
А из какого поля правильно брать объём - Volume или LeftVolume (для StoppLoss-стратегии)?
Сергей Гаврилов, [15.01.15 17:06]
Чего то я такого свойсва не нашел..
Сергей Гаврилов, [15.01.15 17:08]
Вообще-то LeftVolume - это неисполненный остаток объема
Александр Спирин, [15.01.15 17:10]
Мне Visual Studio подсказал... Дело в том, что по-уму-то надо дождаться остановки, и только когда она остановится спрашивать, какой объём остался - такой и защищать.
Владимир (vow001) Русаков, [16.01.15 13:53]
Добрый день, подскажите пжл, какие существуют состояния у создаваемых в Квике заявок (по-моему, активна, исполнена и ещё какие-то) и с помощью какого события можно отслеживать изменения статуса заявки?
Сергей Гаврилов, [16.01.15 14:08]
Там несколько событий OrdersRegisterFailed, NewOrders, OrdersChanged
, и др..
Сергей Гаврилов, [16.01.15 14:09]
OrdersCancelFailed
Сергей Гаврилов, [16.01.15 14:09]
Со стопами - отдельные события..
Сергей Гаврилов, [16.01.15 14:10]
Это события класса Connector
Владимир (vow001) Русаков, [16.01.15 14:11]
Ясно, А как понять, что заявка исполнена? WhenRegistred?
Сергей Гаврилов, [16.01.15 14:11]
А тебе событие для правила нужно..
Сергей Гаврилов, [16.01.15 14:13]
Order.WhenMatched, Order.WhenPartiallyMatched
Сергей Гаврилов, [16.01.15 14:15]
Плюс событие для сделки - Order.WhenNewTrades
Владимир (vow001) Русаков, [16.01.15 14:17]
Спасибо, сейчас тогда в документации найду описание этих событий
Мария Крень, [17.01.15 20:59]
Здравствуйте, подскажите есть ли переменная описывающая минимально и максимально возможную цену в Квике для инструмента?
Мария Крень, [17.01.15 21:00]
это же тоже самое чтои верхний лимит и нижний?
Мария Крень, [17.01.15 21:04]
Почему он по умолчанию ноль?
Сергей Гаврилов, [18.01.15 00:58]
Если Вы под максимальной/минимальной ценой подразумеваете границы изменения цены внутри торговой сессии, то да, это и есть верхний/нижний лимит
Сергей Гаврилов, [18.01.15 01:02]
Вот так попробуйте
baseTrader.RegisterSecurity(Security);
// Пробуем "научить" Квик-Трейдер правильно выставлять маркет-ордера при работе с фьючерсами
//baseTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MaxPrice);
//baseTrader.SecuritiesTable.Columns.Add(DdeSecurityColumns.MinPrice);
Александр Спирин, [18.01.15 12:35]
Приветствую!
Не получается свой индикатор на графике нарисовать - помогите pls:
создаю графический элемент так:
_suppLevelsElem1 = new ChartIndicatorElement
{
Title = "Support Level 1",
Color = Colors.Red,
StrokeThickness = 1
};
_area.Elements.Add(_suppLevelsElem1);
Добавляю на график так:
var sv1 = _strategy.SuppLevels.GetFirstLevel(candle.HighPrice);
var suppValue1 = (sv1 != -1) ? new ChartIndicatorValue(_strategy.SuppLevels, sv1) : null;
var dict = new Dictionary<IChartElement, object>
{
{_candlesElem, candle},
{_upBandElem, upBandValue},
{_lowBandElem, lowBandValue},
{ _suppLevelsElem1, suppValue1 },
};
_chart.Draw(candle.OpenTime, dict);
И получается, что рисуется он у меня с отставанием (уровень возникает после большой красной свечи с длинными тенями в 18:45).
Что я делаю не так?
Александр Спирин, [18.01.15 12:37]
[ Photo ]
Александр Спирин, [18.01.15 12:38]
А на графике получается вот что:
Александр Спирин, [18.01.15 12:38]
Метод GetFirstLevel() фактически возвращает -1, пока уровень не возник.
Сергей Гаврилов, [18.01.15 16:14]
Для начала нужно, просто вывести время и значения идикатора в лог или в окно Output и посмотреть корректно он расчитывается или нет
Александр Спирин, [18.01.15 21:33]
Напечатал: вижу, что первое значение получено в 15-го 10:05, а на графике оно отражено в 14-го, в 21:45
01/14/2015 21:00:00 +03:00: supp. level = -1
01/14/2015 21:05:00 +03:00: supp. level = -1
01/14/2015 21:10:00 +03:00: supp. level = -1
01/14/2015 21:15:00 +03:00: supp. level = -1
01/14/2015 21:20:00 +03:00: supp. level = -1
01/14/2015 21:25:00 +03:00: supp. level = -1
01/14/2015 21:30:00 +03:00: supp. level = -1
01/14/2015 21:35:00 +03:00: supp. level = -1
01/14/2015 21:40:00 +03:00: supp. level = -1
01/14/2015 21:45:00 +03:00: supp. level = -1
01/14/2015 21:50:00 +03:00: supp. level = -1
01/14/2015 21:55:00 +03:00: supp. level = -1
01/15/2015 10:00:00 +03:00: supp. level = -1
01/15/2015 10:05:00 +03:00: supp. level = 73140
01/15/2015 10:10:00 +03:00: supp. level = 73140
01/15/2015 10:15:00 +03:00: supp. level = 73140
01/15/2015 10:20:00 +03:00: supp. level = 73140
01/15/2015 10:25:00 +03:00: supp. level = 73140
Александр Спирин, [18.01.15 21:34]
[ Photo ]
Сергей Гаврилов, [18.01.15 21:43]
Индикатор секретный?
Александр Спирин, [18.01.15 21:43]
да нет...весь код показать?
Сергей Гаврилов, [18.01.15 21:44]
В атачменте скиньте..
Александр Спирин, [18.01.15 21:45]
[ Document : class.cs ]
Сергей Гаврилов, [18.01.15 21:47]
Сами данные откуда берете?
Александр Спирин, [18.01.15 21:50]
Это переделанный пример SampleSmartSma - мне кажется, что Вы быстрее поймёте, заглянув в код примера, чем слушать моё бормотание...
Сергей Гаврилов, [18.01.15 21:51]
ок
Александр Спирин, [18.01.15 21:51]
private void ProcessCandle(Candle candle)
{
if (candle.State == CandleStates.Finished)
{
_strategy.Atr.Process(candle);
_strategy.SuppLevels.Process(candle);
_strategy.RestLevels.Process(candle);
}
_strategy.BollBands.Process(new DecimalIndicatorValue(candle.ClosePrice) { IsFinal = candle.State == CandleStates.Finished });
var upBandValue = new ChartIndicatorValue(_strategy.BollBands, _strategy.BollBands.UpBand.GetCurrentValue());
var lowBandValue = new ChartIndicatorValue(_strategy.BollBands, _strategy.BollBands.LowBand.GetCurrentValue());
var sv1 = _strategy.SuppLevels.GetFirstLevel(candle.HighPrice);
var suppValue1 = (sv1 != -1) ? new ChartIndicatorValue(_strategy.SuppLevels, sv1) : null;
Debug.Print("{0}: supp. level = {1}", candle.OpenTime, sv1);
//var suppValue1 = new ChartIndicatorValue(_strategy.BollBands, _strategy.BollBands.LowBand.GetCurrentValue()-100);
var dict = new Dictionary<IChartElement, object>
{
{_candlesElem, candle},
{_upBandElem, upBandValue},
{_lowBandElem, lowBandValue},
{ _suppLevelsElem1, suppValue1 },
//{ _suppLevelsElem2, new ChartIndicatorValue(_strategy.SuppLevels, _strategy.SuppLevels.GetFirstLevel(candle.HighPrice)) },
//{ _restLevelsElem1, new ChartIndicatorValue(_strategy.RestLevels, candle.ClosePrice+100) },
//{ _restLevelsElem2, new ChartIndicatorValue(_strategy.RestLevels, candle.ClosePrice+100) },
};
_chart.Draw(candle.OpenTime, dict);
}
Сергей Гаврилов, [19.01.15 14:32]
Смотрите, Метод GetFirstLevel() возвращает -1, но не факт ChartIndicatorValue в этот момент Null, ведь на графике у вас в этот момент рисуется линия индикатора, а ее не должно быть вообще
Сергей Гаврилов, [19.01.15 15:32]
Алексей, можете весь проект скинуть?
Александр Спирин, [19.01.15 17:53]
[ Document : SampleSmartSMA.zip ]
Александр Спирин, [19.01.15 17:54]
Так и мне непонятно всё, как индикатор рисуется... Я просто делал как в примере, не особо вдаваясь в детали, но теперь придётся )
Александр Спирин, [19.01.15 18:54]
Сергей, а можете пояснить (чуть отвлекаясь в сторону) что минимально нужно сделать, чтобы у нструмента появился Open Interest? - когда на старте я получаю инструменты, он равен 0, а мне хочется отобрать из всех инструментов те, у которых он достаточно велик. Достаточно будет подписаться на получение котировок? - мне чем меньше усилий, чем лучше. Спасибо.
Сергей Гаврилов, [19.01.15 18:58]
Если честно, я никогда OI не использовал... Но, думаю, что достаточно только подписаться на инструмент.. Дело в том, что в нативном Смарткоме никаких
Сергей Гаврилов, [19.01.15 18:59]
никаких специальных функция для получения OI нет, и если он его транслирует OI должен появиться в свойствах инструмента..
Алексей (AlexGP) Плотников, [19.01.15 19:09]
У меня почему-то:
storageRegistry.GetTradeStorage(Security).Load(Nullable, Nullable) возвращает данные на сутки раннее, при этом:
– storageRegistry.GetTradeStorage(Security).Load(DateTime date) и
– (IEnumerable) storageRegistry.GetTradeStorage(Security).Load(DateTime date)
работают корректно.
Что я не так делаю?
Александр Спирин, [19.01.15 19:16]
а подписаться на инструмент - это Security.WhenChanged?
Сергей Гаврилов, [19.01.15 19:19]
Вы учли то момент, что Гидра грузит данные с лагом в прошлое?
Сергей Гаврилов, [19.01.15 19:20]
на инструмент вы подписываетесь при помощи Connector.RegisterSecurity(Security)
Алексей (AlexGP) Плотников, [19.01.15 19:32]
Я вообще не использую IConnector, нет такого кода т.к. чистый эксперимент со StorageRegistry. Если бы дело было в «..Гидра грузит данные с лагом в прошлое…» то и
- storageRegistry.GetTradeStorage(Security).Load(DateTime date),
- (IEnumerable) storageRegistry.GetTradeStorage(Security).Load(DateTime date),
отрабатывали бы соответствующее. В общем вопрос на повестке…
Сергей Гаврилов, [19.01.15 19:33]
Про коннектор это не вам..\
Алексей (AlexGP) Плотников, [19.01.15 19:33]
да, уже понял... ))
Сергей Гаврилов, [19.01.15 19:35]
Я просто имел ввиду, что если Вы грузите совсем последние данные, то текущая дата может не прийти, т.к. ее нет в Гидре, если так грузится любой диапазон, то это нужно вроверять..
Сергей Гаврилов, [19.01.15 19:40]
To Alex P: у Вас какая версия Гидры?
Алексей (AlexGP) Плотников, [19.01.15 19:51]
Очень даже не совсем последние, а вполне себе исторические, т.к. коннектора к реальному шлюзу нет за неимением шлюза как такового (пока разбираюсь с библиотекой).
Версия Гидры 4.2.50.0. Но дело-то не в Гидре. Имеем разную реакцию методов класса и методов расширения на одинаковые данные. Если нужно проверить, то: «надо, так надо…»
Может я что-то не так делаю (как и спросил в первом сообщении), либо глюк…
Сергей Гаврилов, [19.01.15 19:53]
Конечно, так быть не должно. проверим..
Алексей (AlexGP) Плотников, [19.01.15 20:00]
Ок
Александр Спирин, [19.01.15 23:35]
"на инструмент вы подписываетесь при помощи Connector.RegisterSecurity(Security)" - а в ответ должно событие Connector.SecuritiesChanged срабатывать?
Сергей Гаврилов, [19.01.15 23:37]
Да.