S#.Shell. Manual
Atom
10/14/2013
Kazai Mazai


[b]Часть 1. Starting up[/b]

Первым делом неплохо было бы разобраться с коннекторами.

Уже есть Альфадирект и Квик. Мне бы хотелось подрубить свой кастомный для IB. Но незадача: В каркасе старая версия S#. Это грозит проблемами в работе с гидрой и коннекторами. У меня возникли сразу, потому что коннектор был на 4.1.19.1.

Значит заодно и обновлюсь.

Удаляю все, что связано со stocksharp и Ecng из reference, и добавляю заново все свежее. У меня вот такой список получился.

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/36188/36188_original.png]1[/img]

После обновления, ничего не заработает.

Поправил в ConnectionEngine для квика и для альфа аналогично.

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/36362/36362_original.png]2[/img]

После ребилда все должно взлететь.

Добавил, естественно, нужные Refercences, и создание коннектора по аналогии.

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/36731/36731_original.png]3[/img]

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/37924/37924_original.png]4[/img]

Настройки. Тут есть целый менеджер настроек, который отвечает за сохранение, и т.д.

Добавил в список коннекторов и нужные настройки в SettingsProperties

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/37050/37050_original.png]5[/img]

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/37292/37292_original.png]6[/img]

Ну вот и все.

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/37561/37561_original.png]7[/img]

[img=http://ic.pics.livejournal.com/kazai_trader/23836215/37705/37705_original.png]7[/img]



< 1 2 3  >
Aton5

Avatar
Date: 1/15/2014
Reply


где взять исходники S#.Shell, тем у кого лицензия это позволяет? Дайте, пожалуйста, ссылку.

Thanks:

dij1

Avatar
Date: 1/18/2014
Reply


скачал версию 4.2.2, там вообще Shell не открывается, библиотек основных нет.

Thanks:

JaguarFX

Avatar
Date: 2/12/2014
Reply


Месяц прошел - и молчание разработчиков!)) На самом деле Shell действительно достаточно сырой продукт, в который необходимо много вложить чтобы получить выхлоп. Даже в версии от Казакова Сергея достаточно ошибок и неточностей, на исправление которых у меня ушло множество времени.

Так почти месяц назад я поставил для себя цель провести миграцию своих торговых роботов с платформы TradeMatic на платформу S#.Shell, и за это время наработал материал, которым стоит поделиться дабы не возникали подобные вопросы.

Thanks:

JaguarFX

Avatar
Date: 2/12/2014
Reply


[b]Часть 4. Универсализация создания, тестирования и исполнения стратегий[/b]

Первое что мне бросилось в глаза в версии от Kazai Mazai, которую я продолжил допиливать - отсутствие универсальности в исполнении/тестировании одной и той же стратегии. Так если запустить стратегию RobotStrategy на тестирование, то следующий участок кода стратегии: [code=csharp] ... lock (this) { if (_bidOrder == null && _askOrder == null) { // проверяем на сигнал на вход var spread = (ask - bid) / Security.MinStepSize;

	if (spread >= ((RobotStrategyProperties)Params).Spread)

... [/code] вызовет ошибку "Не удалось привести тип объекта "System.Collections.Generic.List1[Robot.Strategies.HustleEveryDayStrategyTestingProperties]" к типу "System.Collections.Generic.List1[Robot.Strategies.HustleEveryDayStrategyProperties]".

Для решения этой проблемы введем в класс BaseShellStrategyProperties два параметра "Класс стратегии" и "Режим запуска": [CODE=csharp]

    public enum enMode
    {
       Execution,
       Testing
    }

    private string _classname = "Класс стратегии";
    [DisplayName(@"Класс")]
    [Description(@"Класс стратегии")]
    [Category(@"Основные")]
    [PropertyOrder(1)]
    public string ClassName
    {
        get { return _classname; }
        set
        {
            _classname = value;
            OnPropertyChanged("ClassName");
        }
    }


    private enMode _mode = enMode.Testing;
    [Category(@"Основные")]
    [DisplayName(@"Режим запуска")]
    [Description(@"Режим запуска стратегии")]
    [PropertyOrder(2)]
    public enMode Mode
    {
        get { return _mode; }
        set
        {
            _mode = value;
            OnPropertyChanged("Mode");
        }
    }

[/CODE]

Данные свойства необходимо определять во всех процедурах типа AddХХХХStrategy. [CODE=csharp] private void AddRobotStrategy() { var properties = new RobotStrategyProperties { ClassName = "Robot", Mode = enMode.Execution [/CODE]

4.1. Универсализация исполнения стратегий Все параметры внутри стратегии обертываем процедурой if, которая проверяет режим запуска и проводит правильное приведение типов данных: [CODE=csharp] int StopVal = 1; if (Params.Mode == enMode.Execution) StopVal = ((RobotStrategyProperties)Params).Stop; else StopVal = ((RobotTestingProperties)Params).Stop; [/CODE]

4.2. Универсализация тестирования стратегий В основную процедуру запуска стратегий на тестирование StartTesingStrategy добавляем проверка класса стратегии при задании специфичных параметров: [CODE=csharp] if (parameters.ClassName == "Sma" || parameters.ClassName == "TLS") { switch (parameters.ClassName) { case "Sma": ((SmaStrategy)_strategy).series = _series; break; case "TLS": ((TLSStrategy)_strategy).series = _series; break; } } [/CODE]

4.3. Универсализация сохранения настроек стратегий В основной процедуре сохранения настроек стратегии SaveStrategies проводим модификацию запроса Where [CODE=csharp] var robotstrategies = _documents.Keys.Where(str => str.Params.ClassName == "Robot" && str.Params.Mode == enMode.Execution).Select(str => (RobotStrategyProperties)str.Params).ToList(); SettingsEngine.Instance.SaveRobotStrategies(robotstrategies);

var hustlestrategies = _documents.Keys.Where(str => str.Params.ClassName == "Hustle" && str.Params.Mode == enMode.Execution).Select(str => (HustleStrategyProperties)str.Params).ToList(); SettingsEngine.Instance.SaveHustleStrProp(hustlestrategies); [/CODE]

4.4. Устранение бага отображения стратегий на панели "Стратегии" В поставляемой версии на панели "Стратегии" не отражаются тестовые стратегии. Для устранения этого бага проводим универсализацию хранения стратегий в переменной _documents. а) везде в процедурах создания стратегий проводим сохранение стратегий в переменную _documents: [CODE=csharp] _documents.Add(strategy, doc); [/CODE] б) в свойстве SelectedStrategy дописываем условие выбора документа типа TestingDocument: [CODE=csharp] var doc = dockManager.ActiveContent;

            if (doc is StrategyDocument)
            {
                var content = (StrategyDocument)doc;
                result = content.Strategy;
            }
            else
            {
                var content = (TestingDocument)doc;
                result = content.Strategy;
            }
            return result;

[/CODE] Теперь все отображается корректно. в) дополнительно можно вообще удалить процедуру SaveTestingStrategies, поместив соответствующие обработки в SaveStrategies: [CODE=csharp] var robotTstrategies = _documents.Keys.Where(str => str.Params.ClassName == "Robot" && str.Params.Mode == enMode.Testing).Select(str => (RobotStrategyTestingProperties)str.Params).ToList(); SettingsEngine.Instance.SaveRobotTestingStrategies(robotTstrategies);

var hustleTstrategies = _documents.Keys.Where(str => str.Params.ClassName == "Hustle" && str.Params.Mode == enMode.Testing).Select(str => (HustleStrategyTestingProperties)str.Params).ToList(); SettingsEngine.Instance.SaveHustleTestStrProp(hustleTstrategies); [/CODE]

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

StrategyPane.jpg 253 KB (416)
Thanks:

JaguarFX

Avatar
Date: 2/16/2014
Reply


[b]Часть 5. Чему нас учит семья и школа[/b]

Интерфейс тестирования S#.Shell по умолчанию не достаточен для эффективного тестирования стратегии при ее первичном кодировании, так как в этом тонком процессе переноса собственного нейронного вещества в машинный код возникает множество нюансов а-ля "сделка не выполнилась в силу неизвестных причин", в которых невозможно разобраться без соответствующих инструментов.

Поэтому добавляем в наш S.Shell основные инструменты визуализации процесса исполнения стратегии, которые нам уже знакомы по курсу S#.Education - исторический график свечей, таблицу заявок и таблицу собственных сделок.

5.1. Создаем на TestingPanel элемент типа TabControl, в который добавляем вкладки для каждого инструмента: [code=java] <chart:Chart x:Name="HistoryChart" MinHeight="200" Height="Auto" x:FieldModifier="public"/> <chart:EquityCurveChart x:Name="CurveChart" MinHeight="200" Height="Auto" x:FieldModifier="public"/> <xaml:OrderGrid x:Name="myOrders" MinHeight="200" Height="Auto" x:FieldModifier="public"/> <xaml:MyTradeGrid x:Name="myTrades" MinHeight="200" Height="Auto" x:FieldModifier="public"/> [/code]

5.2. В общем-то мы понимаем, что графические элементы в целом тормозят тестирование и нужны будут не всегда, а в основном при кодинге новых стратегий, поэтому в свойства базовой стратегии тестирования BaseShellStrategy добваляем свойства для управления отображением их в ходе тестирования: [code=csharp] private bool _chartPL = false; [Category(@"Отрисовка")] [DisplayName(@"График P&L")] [Description(@"Вывод графика P&L при тестировании")] [PropertyOrder(0)] public bool chartPL { get { return _chartPL; } set { _chartPL = value; OnPropertyChanged("chartPL"); } }

    private bool _chartHC = false;
    [Category(@"Отрисовка")]
    [DisplayName(@"График свечей")]
    [Description(@"Вывод графика свечей  при тестировании")]
    [PropertyOrder(2)]
    public bool chartHC
    {
        get { return _chartHC; }
        set
        {
            _chartHC = value;
            OnPropertyChanged("chartHC");
        }
    }

    private bool _chartTrd = false;
    [Category(@"Отрисовка")]
    [DisplayName(@"Сделки")]
    [Description(@"Вывод всех сделок на график истории")]
    [PropertyOrder(2)]
    public bool chartTrd
    {
        get { return _chartTrd; }
        set
        {
            _chartTrd = value;
            OnPropertyChanged("chartTrd");
        }
    }

[/code]

5.3. В процедуре тестирования стратегии StartTesingStrategy прописываем код для обоработки каждого нового инструмента: а) для истории свечей: [code=csharp] if (parameters.chartHC) { histChart = doc.TestingPanel.HistoryChart; histChart.Areas.Clear(); histChart.IsAutoScroll = true; _area = new ChartArea(); //создаем область на графике histChart.Areas.Add(_area); //добавляем область на график _candlesElem = new ChartCandleElement(); //создаем элемент свечи _area.Elements.Add(_candlesElem); //добавляем элемент в область вывода графика _candleManager.Processing += (series, cnd) => { if (cnd.State == CandleStates.Finished) { var myDic = new Dictionary<IChartElement, object>(); myDic.Add(_candlesElem, cnd); MainWindow.Instance.GuiAsync(() => histChart.ProcessValues(cnd.OpenTime, myDic)); } }; } [/code] б) для отражения истории сделок: [code=csharp] if (parameters.chartHC && parameters.chartTrd) { var _tradeElement = new ChartTradeElement(); _area.Elements.Add(_tradeElement); _strategy.NewMyTrades += (trds) => trds.ForEach(t => { var tradeTime = _timeFrame.GetCandleBounds(t.Trade.Time).Min; var myDic = new Dictionary<IChartElement, object>() { { _tradeElement, t } }; MainWindow.Instance.GuiAsync(() => histChart.ProcessValues(tradeTime, myDic)); }); } [/code] в) для таблицы заявок: [code=csharp] var _myOrders = doc.TestingPanel.myOrders; _myOrders.Orders.Clear(); _strategy.OrderRegistered += (ord) => MainWindow.Instance.GuiAsync(() => _myOrders.Orders.Add(ord)); [/code] г) для таблицы сделок: [code=csharp] var _myTrades = doc.TestingPanel.myTrades; _myTrades.Trades.Clear(); _strategy.NewMyTrades += (trd) => trd.ForEach(t => MainWindow.Instance.GuiAsync(() => _myTrades.Trades.Add(t))); [/code]

И в результате все работет отлично, кроме корректного отображения сделок))

History.jpg 529 KB (414) Orders.jpg 710 KB (430) MyTrades.jpg 430 KB (420)
Thanks:

kesot

Avatar
Date: 2/20/2014
Reply


А почему для установки стопов не пользуетесь StopLossStrategy, а в ручную их отслеживаете?

Thanks:

JaguarFX

Avatar
Date: 2/24/2014
Reply


на мой взгляд использование дочерних стратегий тут дело вкуса - кому-то идет, а кому-то нет; в силу разных обстоятельств - и дебаггить их невозможно, условия срабатывания ограничены (н--р нет стоп-лосса исходя из % годовых) и пр.

Thanks:

JaguarFX

Avatar
Date: 3/1/2014
Reply


[b]Часть 6 - Тотальный апгрейд[/b]

Итак имеем S#.Shell на основе S#.API 4.1.15.0 и решаемся на апгрейд до версии 4.2.2.16. Сразу же получаем множество заменой iTrader на Connector, и еще с десяток проблемных мелочей типа замены свойств, которые решаются в течение получаса

Но так же вылезают две более серьезные проблемы, о которых имеет смысл тут рассказать.

  1. В XAML отваливается весь CommandBinding с тупым сообщением "Член не распознан")) Как единственное найденное 100% работающее решение данной проблемы - перенос всего CommandBindingа из XAML в программный код. Для этого делаем три простых шага:
  1. в MainWindow.xaml полностью удаляем содержание раздела <Window.CommandBindings> и привязки команд типа Command="", а вместо этого для каждого элемента, которому необходимо привязать RoutedCommand задаем имя через тег x:Name
  2. в MainWindow.xaml.cs создаем новую процедуру private void InitializeCommands(), в которой для каждого управляющего элемента создаем связь через класс CommandBinding (на примере пункта меню "Подключиться"): [CODE=csharp] CommandBinding ccBinding1 = new CommandBinding(ConnectCommand, ExecutedConnect, CanExecuteConnect); this.CommandBindings.Add(ccBinding1); miConnect.Command = ConnectCommand; [/CODE] где ConnectCommand - исходная RoutedCommand, ExecutedConnect - основная процедура для выполнения, CanExecuteConnect - связанная проверочная процедура возможности выполнения основной процедуры, miConnect - название элемента пункта меню "Подключиться", далее в тоже процедуре InitializeCommands() создаем необходимые элементы для быстрых клавиш: [CODE=csharp] KeyGesture OpenKeyGesture1 = new KeyGesture(Key.P,ModifierKeys.Control); InputBinding KeyBinding1 = new KeyBinding(SettingsCommand, OpenKeyGesture1); this.InputBindings.Add(KeyBinding1); [/CODE]
  3. вызываем InitializeCommands() в теле процедуры MainWindow().
  1. В S#.API версии 4.2.2.16 обнаруживаем, что в режиме эмуляции ни один из коннекторов (проверено на AlfaTrader/TransaqTrader) не получает портфели. Соответственно тестирование в эмуляции невозможно. Для решения этой проблемы делаем два шага:
  1. создаем в классе ConnectionEngine свойство IsEmulation: [CODE=csharp] public bool IsEmulation { get { return settings.Emulation; } } [/CODE] 2)добавляем в код процедуры StartStrategy специальную проверку на режим эмуляции и в случае оного, создаем тестовый портфель, который и привязываем к коннектору: [CODE=csharp] var portfolio = ConnectionEngine.Instance.Trader.Portfolios.FirstOrDefault(p => p.Name == strategy.Params.Portfolio); if (portfolio == null) { if (ConnectionEngine.Instance.IsEmulation) { var portf = new Portfolio{Name = "TestAcc",BeginValue = 1000000,CurrentValue = 1000000}; ConnectionEngine.Instance.Trader.RegisterPortfolio(portf); ConnectionEngine.Instance.Trader.TransactionAdapter.SendInMessage(portf.ToMessage()); var pcm =new PortfolioChangeMessage.Add(PositionChangeTypes.BeginValue, portf.BeginValue); ConnectionEngine.Instance.Trader.TransactionAdapter.SendInMessage(pcm); var pcm2 = new PortfolioChangeMessage .Add(PositionChangeTypes.CurrentValue, portf.CurrentValue); ConnectionEngine.Instance.Trader.TransactionAdapter.SendInMessage(pcm2); strategy.Portfolio = portf; strategy.AddWarningLog("Создан портфель {0} для запуска стратегии", portf.Name); } else { strategy.AddErrorLog("Не найден портфель {0} для запуска стратегии", strategy.Params.Portfolio); return;
    }

         }
         else
             strategy.Portfolio = portfolio;
    

[/CODE]

Вуаля- все работает как нужно!

Thanks: methyst

methyst

Avatar
Date: 3/10/2014
Reply


lebedevsrg, собираетесь ли Вы выкладывать свою версию shell'a куда-нибудь?

Thanks:

JaguarFX

Avatar
Date: 3/10/2014
Reply


methyst, тут такие правила что по окончанию срока обучения (1,5 или 3 мес ) пользователей отключают от TFS. По вопросу - полагаю что смысла каждому пользователю выкладывать свои программы на TFS особого нет. Материалы я тут опубликовал для общего развития тех кто захочет сам допиливать Shell.

Thanks:
< 1 2 3  >

Attach files by dragging & dropping, , or pasting from the clipboard.

loading
clippy