StopLoss и тестирование на истории
Atom
12.09.2012


Gii

Фотография
Добрый день!
Суть проблемы, начиная с версии StockSharp 4.1.3 (далее SS) не работает StopLoss,причем только с EmulationTrader. Более корректно - при включенном IsTrailing = true, StopLoss ведет себя как будто IsTrailing отключен. Конечно это суждение основанное только на результатах теста, что реально происходит мне неизвестно.
1. Для приготовления теста взят "SampleHistoryTesting" "SS 4.1.4" из него удален класс SmaStrategy и вставлен простой класс для тестирования StopLoss приведенный ниже.
2. Тестирование проводилось на всех SS начиная с версии "SS 4.1.2" и заканчивая "SS 4.1.4 bild 19213"
3. Тестирование проводилось на одних и тех же данных "SBER@EQBR" 02.05.12 по 10.08.12. Тиковые сделки получены через программу "Hydra (SS 4.1.3)", а так же "RIU9@RTS"
4. Тестирование проводилось с разными значениями ProtectiveLevel начиная с минимального =Security.MinStepSize.
5. Для исключения влияния характера исходных данных на полученный результат менялась дата начала теста. Картина в целом оставалась такой же, менялось только количество сделок StopLoss стратегии совершенных в начале тестирования.

Результаты тестирования
1. В версии "SS 4.1.2" получен адекватный результат, ниже приведен фрагмент лога и картинка работы стратегии
2. Начиная с версии "SS 4.1.3" результаты были повторяющимися но не соответствующими ожиданиям в приведенном ниже логе и на картинке видно как StopLoss срабатывает один раз а затем после следующей сделки находясь в активном режиме не реагирует на изменение цены даже при ProtectiveLevel=Security.MinStepSize.

С уважением GII

Код

using System;
using System.Collections.Generic;
using System.Linq;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Logging;
using StockSharp.Algo;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;

namespace SampleHistoryTesting
{
    class MyStopLossStrategy : Strategy
    {
        private readonly CandleSeries _series;
        private readonly TimeSpan _timeFrame;
        private Exchange _excheng;
        private Random _random;
        private Order _order=new Order();
        private static readonly object Locker = new object ();

        public MyStopLossStrategy( CandleSeries series, TimeSpan timeFrame )
        {
            _series = series;
            _timeFrame = timeFrame;
        }

        protected override void OnStarted()
        {
            _excheng = Security.Exchange;
            _series
                .WhenCandlesFinished ()
                .Do ( ProcessCandle ).Apply ( this );
            
            // Инициализируем генератор случ величин
            _random = new Random ( 1 );
            base.OnStarted ();
        }

        private void ProcessCandle( Candle candle )
        {

            /* Три условия вхождения в сделку 
             * 1. пришла последняя свечка
             * 2. Protective стратегия больше не активна
             */
            var lastTime = _timeFrame.GetCandleBounds ( Trader.GetMarketTime (_excheng) ).Min - _timeFrame;

            #region InfoLog
            this.AddInfoLog(string.Format("LastTime / candle.OpenTime // {0} / {1} //", lastTime, candle.OpenTime));
            this.AddInfoLog(string.Format("StopLoss (активна -true) = {0}", IsActiveChildStrat()));
            #endregion

            lock (Locker)
            {
                //var lastTime = Trader.GetMarketTime ( _excheng );
                //var endInterval = candle.CloseTime + TimeSpan.FromSeconds ( 5 );
                if (lastTime <= candle.OpenTime)
                {
                    if (_order.State == OrderStates.Active) CancelActiveOrders ();
                    if (!IsActiveChildStrat ())
                    {
                        _order = null;
                        // Определяем направление сделки
                        var rd = 1 - 2 * _random.NextDouble (); // -1 < rd < 1
                        var direction = OrderDirections.Sell;
                        if (rd >= 0) direction = OrderDirections.Buy;
                        _order = this.CreateOrder ( direction, (decimal)Security.GetCurrentPrice ( direction ), Volume );
                        //Обрабатываем новые сделки только от _order.
                        _order.WhenNewTrades ().Do ( NewMyTrade ).Apply ( this );
                        RegisterOrder ( _order );
                        this.AddOrderInfoLog ( _order, "" );
                    }
                }
            }
        }

        private void NewMyTrade( IEnumerable<MyTrade> trades )
        {
            try
            {
                lock (Locker)
                {
                    var trade = trades.Last ();
                    
                    var sl = new StopLossStrategy ( trade, (int)UnitTypes.Absolute )
                        {
                            IsTrailing = true,
                            ProtectiveLevel =Security.MinStepSize,
                            Security = Security,
                        };
                    
                    // Удоляем следы работы дочерней стратегии
                    sl.WhenStopped ().Do ( strategy =>
                        {
                            ChildStrategies.Remove ( strategy );
                            this.AddInfoLog ( string.Format ( "Кол. StopLoss активных стратегий = {0}",ChildStrategies.Count));
                        } ).Once ().Apply ( this );
                    ChildStrategies.Add ( sl );

                    this.AddInfoLog ( string.Format ( "ProtectivePrice / ProtectiveDirection= //{0} / {1} ", sl.ActivationPrice.ToString("F2"), sl.ProtectiveDirection.ToString() ) );
                    this.AddInfoLog ( string.Format ( "StopLoss = {0}", sl.IsActivated.ToString() ) );
                }
            }
            catch (Exception e)
            {
                this.AddErrorLog ( string.Format ( "<NewMyTrade> Err {0}", e ) );
            }
        }

        /* Метод проверяет активность одной из нескольких стратегий, 
        * если хотя бы одна активна возвращает true
        */
        public bool IsActiveChildStrat()
        {
            try
            {
                if (ChildStrategies.Count == 0) return false;
                if (ChildStrategies.Count > 0) return true;
                /* 
                if (ChildStrategies.Any ( childStrategy => childStrategy.ProcessState == ProcessStates.Started || childStrategy.ProcessState == ProcessStates.Stopping ))
                {
                    return true;
                }
                */
            }
            catch (Exception e)
            {
                this.AddErrorLog ( string.Format ( "<IsActiveChildStrat> Err {0}", e ) );
            }
            return false;
        }

        protected override void OnStopping()
        {
            //останавливаем все доч. стратегии
            foreach (var str in ChildStrategies) { str.Stop (); }
            ChildStrategies.Clear ();
            CancelActiveOrders ();
            base.OnStopping ();
        }

    }
}

log SS 4-1-4.txt 4 MB (259) SS 4-1-4.jpg 256 KB (204) log SS-4-1-2.txt 3 MB (226) SS 4-1-2.jpg 163 KB (181) MainWindow.xaml 2 KB (241) MainWindow.xaml.cs 10 KB (195) MyStopLossStrategy.cs 5 KB (160)

Теги:


Спасибо:


Alexander

Фотография
Дата: 13.09.2012
Ответить


Посмотрим, спасибо за конкретные исходники на которых можно попытаться воспроизвести
Спасибо:

Mikhail Sukhov

Фотография
Дата: 13.09.2012
Ответить


Можете проверить, изменилось ли поведение после последнего коммита?
Спасибо:

Gii

Фотография
Дата: 14.09.2012
Ответить


Mikhail Sukhov Перейти
Можете проверить, изменилось ли поведение после последнего коммита?

Добрый день!
Михаил извините, но я не совсем понял что вы имели в виду под "коммит", если build 19259 то не помогло.

С уважением GII
Спасибо:

Mikhail Sukhov

Фотография
Дата: 14.09.2012
Ответить


Gii Перейти
Mikhail Sukhov Перейти
Можете проверить, изменилось ли поведение после последнего коммита?

Добрый день!
Михаил извините, но я не совсем понял что вы имели в виду под "коммит", если build 19259 то не помогло.

С уважением GII


Тогда разберем ситуацию. Можно привести более короткий диапазон времени (час-полчаса) для теста? И лог за непосредственно неправильный период, должно быть где-то порядка нескольких минут, если у вас стоп не очень большой.
Спасибо:

Gii

Фотография
Дата: 14.09.2012
Ответить


Mikhail Sukhov Перейти
Gii Перейти
Mikhail Sukhov Перейти
Можете проверить, изменилось ли поведение после последнего коммита?

Добрый день!
Михаил извините, но я не совсем понял что вы имели в виду под "коммит", если build 19259 то не помогло.

С уважением GII


Тогда разберем ситуацию. Можно привести более короткий диапазон времени (час-полчаса) для теста? И лог за непосредственно неправильный период, должно быть где-то порядка нескольких минут, если у вас стоп не очень большой.


Добрый день!

Код
var timeFrame = TimeSpan.FromMinutes(2);


все остальное как в первом сообщении, логи прикрепил.

Михаил не могли бы вы решить еще одну проблему, при использовании новых сборок начиная 18833 при компилировании кода (индикаторов)
Код
MacdH.Process((DecimalIndicatorValue) candle.ClosePrice);

выдается ошибка
Цитата:
Ошибка 1 Тип "StockSharp.Algo.Indicators.DecimalIndicatorValue" существует как в "c:\Users\Gii\Documents\Visual Studio 2010\Projects\Pulse v4.5 (SS 4-1-4 bild 0 NewChart)\WpfApplication1\bin\Debug\StockSharp.Algo.Indicators.dll", так и в "i:\C#\StockSharp\Дистрибутивы\stocksharp-19263\trunk\References\StockSharp.Algo.dll" C:\Users\Gii\Documents\Visual Studio 2010\Projects\Pulse v4.5 (SS 4-1-4 bild 0 NewChart)\WpfApplication1\PulseStrategy.cs 217 32 Pulse


С уважением GII.
log SS 4-1-2.txt 1 MB (265) log SS 4-1-4.txt 680 KB (250)
Спасибо:

Mikhail Sukhov

Фотография
Дата: 18.09.2012
Ответить


Gii Перейти

все остальное как в первом сообщении, логи прикрепил.


Интересовали логи именно стратегии, где показан ход работы защитной стратегии. Плюс выделенный проблемный участок.

Для ускорения решения проблемы (если, конечно же, она есть, а не обычное непонимание пессимистичного сценарий тестирования) лучше проделать работу по анализу самостоятельно.
Спасибо:


Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy