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

StopLoss и тестирование на истории
Atom
9/12/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

Code

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 (329) SS 4-1-4.jpg 256 KB (237) log SS-4-1-2.txt 3 MB (293) SS 4-1-2.jpg 163 KB (214) MainWindow.xaml 2 KB (316) MainWindow.xaml.cs 10 KB (253) MyStopLossStrategy.cs 5 KB (193)

Tags:


Thanks:


Alexander

Avatar
Date: 9/13/2012
Reply


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

Mikhail Sukhov

Avatar
Date: 9/13/2012
Reply


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

Gii

Avatar
Date: 9/14/2012
Reply


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

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

С уважением GII
Thanks:

Mikhail Sukhov

Avatar
Date: 9/14/2012
Reply


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

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

С уважением GII


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

Gii

Avatar
Date: 9/14/2012
Reply


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

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

С уважением GII


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


Добрый день!

Code
var timeFrame = TimeSpan.FromMinutes(2);


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

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

выдается ошибка
Quote:
Ошибка 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 (321) log SS 4-1-4.txt 680 KB (317)
Thanks:

Mikhail Sukhov

Avatar
Date: 9/18/2012
Reply


Gii

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


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

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


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

loading
clippy