← Back

Проблемы со стратегией

Вот пытаюсь переписать код грамотно, создать отдельный Stratagy.cs, где будет сама стратегия, но не получается.. Вызывал, вызывал эту стратегию, проверял все ли данные получаю (портфель, инструмент, стакан и тп..) все нормально слава Богу))

Подскажите пожалуйста, как из другого класса вызвать окошко с ошибкой ```csharp MessageBox.Show(this, "тра та та");


И посмотрите пожалуйста кто нить, в чем же ошибка может быть, там всего путь поменять, да счет)) версия последняя 4.0.20 и терменал квик

Comments (31)

Login or Create account, Log in or register to leave a comment

tmt
tmt Author

кстати, 4.0.20 выходит не последняя версия)) надо 4.1 попробовать

freelancer
freelancer

Не надо MessageBox. Почитайте про логирование: http://stocksharp.com/doc/html/82437493-cd53-41eb-b756-d913af0f4f8e.htm Оно вам всё равно понадобится

tmt
tmt Author

freelancer: Не надо MessageBox. Почитайте про логирование: http://stocksharp.com/doc/html/82437493-cd53-41eb-b756-d913af0f4f8e.htm Оно вам всё равно понадобится Мнеб пример с логированием стратегии, но думаю сначало бы разобраться с этой проблемой.

Тыкал тыкал я и натыкал вот такой код


namespace Sample
{
    class NewStrategy : Strategy
    {
        private static MarketDepth _marketDepth;
        private static Position _position;

        protected override void OnStarting()
        {
            this
                .When(Security.MarketDepthChanged())
                .Do(str);

            base.OnStarting();
        }

        public void str()
        {
            shortPos();
            longPos();
            
        }
        
        public void longPos()
        {
            // создаем заявку для открытия длинной позиции
            var longPos = new Order
            {
                Portfolio = Portfolio,
                Price = Security.ShrinkPrice(Security.BestBid.Price),
                Security = Security,
                Volume = 1,
                Direction = OrderDirections.Buy,
            };

            // регистрируем правило, отслеживающее появление новых сделок по заявке
            this
            .When(longPos.NewTrades())
            .Do(OnNewOrderTrades)
            .Periodical(() => longPos.IsMatched());

            // отправляем заявку на регистрацию
            RegisterOrder(longPos);
        }

        public void shortPos()
        {
            // создаем заявку для открытия длинной позиции
            var shortPos = new Order
            {
                Portfolio = Portfolio,
                Price = Security.ShrinkPrice(Security.BestAsk.Price),
                Security = Security,
                Volume = 1,
                Direction = OrderDirections.Sell,
            };

            // регистрируем правило, отслеживающее появление новых сделок по заявке
            this
            .When(shortPos.NewTrades())
            .Do(OnNewOrderTrades)
            .Periodical(() => shortPos.IsMatched());

            // отправляем заявку на регистрацию
            RegisterOrder(shortPos);
        }

        private void OnNewOrderTrades(IEnumerable<MyTrade> trades)
        {
            // для каждой сделки добавляем для защитную пару стратегии
            var protectiveStrategies = trades.Select(t =>
            {
                // выставляет тейк-профит в 100 пунктов
                var takeProfit = new TakeProfitStrategy(t, 100);

                // выставляет стоп-лосс в 50 пунктов
                var stopLoss = new StopLossStrategy(t, 50);

                return new TakeProfitStopLossStrategy(takeProfit, stopLoss);
            });

            ChildStrategies.AddRange(protectiveStrategies);
        }
        
    }
}

ничего не происходило => проблемы со стаканом, он не обновляется.. и функция str() вовсе не вызыватся.

после чего я сделал вот так

        protected override void OnStarting()
        {
            shortPos();
        }

и у меня огромная ошибка

OvcharenkoVI
OvcharenkoVI

tmt:

freelancer: Не надо MessageBox. Почитайте про логирование: http://stocksharp.com/doc/html/82437493-cd53-41eb-b756-d913af0f4f8e.htm Оно вам всё равно понадобится Мнеб пример с логированием стратегии, но думаю сначало бы разобраться с этой проблемой.

Тыкал тыкал я и натыкал вот такой код

namespace Sample { class NewStrategy : Strategy { private static MarketDepth _marketDepth; private static Position _position;

    protected override void OnStarting()
    {
        this
            .When(Security.MarketDepthChanged())
            .Do(str);

        base.OnStarting();
    }

    public void str()
    {
        shortPos();
        longPos();
        
    }
    
    public void longPos()
    {
        // создаем заявку для открытия длинной позиции
        var longPos = new Order
        {
            Portfolio = Portfolio,
            Price = Security.ShrinkPrice(Security.BestBid.Price),
            Security = Security,
            Volume = 1,
            Direction = OrderDirections.Buy,
        };

        // регистрируем правило, отслеживающее появление новых сделок по заявке
        this
        .When(longPos.NewTrades())
        .Do(OnNewOrderTrades)
        .Periodical(() => longPos.IsMatched());

        // отправляем заявку на регистрацию
        RegisterOrder(longPos);
    }

    public void shortPos()
    {
        // создаем заявку для открытия длинной позиции
        var shortPos = new Order
        {
            Portfolio = Portfolio,
            Price = Security.ShrinkPrice(Security.BestAsk.Price),
            Security = Security,
            Volume = 1,
            Direction = OrderDirections.Sell,
        };

        // регистрируем правило, отслеживающее появление новых сделок по заявке
        this
        .When(shortPos.NewTrades())
        .Do(OnNewOrderTrades)
        .Periodical(() => shortPos.IsMatched());

        // отправляем заявку на регистрацию
        RegisterOrder(shortPos);
    }

    private void OnNewOrderTrades(IEnumerable<MyTrade> trades)
    {
        // для каждой сделки добавляем для защитную пару стратегии
        var protectiveStrategies = trades.Select(t =>
        {
            // выставляет тейк-профит в 100 пунктов
            var takeProfit = new TakeProfitStrategy(t, 100);

            // выставляет стоп-лосс в 50 пунктов
            var stopLoss = new StopLossStrategy(t, 50);

            return new TakeProfitStopLossStrategy(takeProfit, stopLoss);
        });

        ChildStrategies.AddRange(protectiveStrategies);
    }
    
}

}

> 
> ничего не происходило => проблемы со стаканом, он не обновляется.. и функция str() вовсе не вызыватся.
> 
> после чего я сделал вот так
> 
> ```csharp
        protected override void OnStarting()
        {
            shortPos();
        }

и у меня огромная ошибка

1.Где вызывается стакан? Не видно метода Trader.RegisterQuotes(Security) или Trader.GetMarketDepth(security). Странно, что ошибка в 90 строке файла strategy, а у вас всего их 86) Посмотрите, что у вас с Security, как вы создаете стратегию, вообще передаете Security из главного окна в стратегию.

Желательно выложить весь проект, тогда будет видно что откуда берется.

P.S.Не работал с квиком никогда, может быть проблема в настройках таблиц? Из за этого допустим стакан не получаете.

tmt
tmt Author

OvcharenkoVI: Не видно метода Trader.RegisterQuotes(Security) или Trader.GetMarketDepth(security). Всем спасибо, ошибка была в том, что я не начал получать стакан "Trader.RegisterQuotes(Security)"🙂

Alexander
Alexander

4.0.20 - последняя final версия. 4.1 в процессе разработки находится, там прилично изменений. Лучше работайте с 4.0.20, на 4.1 у вас ещё больше вопросов возникнет.

hobo
hobo

Начните с самого простого варианта: оставьте только OnStarting, посмотрите что у вас с Security, вызовите из этого же метода стакан,.. Еще рекомендую поискать на форуме, куча рабочих вариантов основ стратегий

tmt
tmt Author

Весь проект выше выложен, стакан надо вызывать до старта стратегии? если да, то думаю в этом и ошибка)

А про примеры, там все примеры с машками, а мне со стаканом надо бы, вот и пытаюсь сделать.

Спасибо, за ответы, буду дальше делать

tmt
tmt Author

Вот одно дело я сделал))) получил вроде как грамотный код, те уже более понятный для гуру. Теперь я попытался его перенести в пример тестирования по истории! Но у меня ничего не вышло, помогите пожалуйста разобраться. Саму стратегию думаю нету смысла выкладывать, тк она явно рабочая.

а вот это файлик MainWondow

namespace SampleHistoryTesting
{
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.IO;
	using System.Windows;
	using System.Windows.Forms;
	using System.Windows.Media;
	using MessageBox = System.Windows.MessageBox;

	using Ecng.Common;
	using Ecng.Serialization;
	using Ecng.Xaml;
	using Ecng.Collections;

	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Reporting;
	using StockSharp.Algo.Storages;
	using StockSharp.Algo.Strategies;
	using StockSharp.Algo.Testing;
	using StockSharp.Algo.Logging;
	using StockSharp.Algo.Equity;
	using StockSharp.Algo.Indicators.Trend;
	using StockSharp.BusinessEntities;

    using System.Linq;

	
	public partial class MainWindow
	{
		private Strategy _strategy;

		private ICollection<EquityData> _curveItems;
		private EmulationTrader _trader;

		private readonly LogManager _logManager = new LogManager();

		private DateTime _lastUpdateDate;
		private DateTime _startEmulationTime;

        public static MarketDepth _marketDepth;
        public static Position _position;

        public static int pos = 2; // 0 - buy; 1 - sell
        public static decimal posPrice = 0;
        public static long posId;
        public static int i;

		public MainWindow()
		{
			InitializeComponent();

			_logManager.Listeners.Add(new FileLogListener("log.txt"));
		}

		private void FindPath_Click(object sender, RoutedEventArgs e)
		{
			var dlg = new FolderBrowserDialog();

			if (!HistoryPath.Text.IsEmpty())
				dlg.SelectedPath = HistoryPath.Text;

			if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				HistoryPath.Text = dlg.SelectedPath;
			}
		}

		private void StartBtn_Click(object sender, RoutedEventArgs e)
		{
			// если процесс был запущен, то его останавливаем
			if (_trader != null && _trader.State != EmulationStates.Stopped)
			{
				StartBtn.IsEnabled = false;

				_strategy.Stop();
				_trader.Stop();
				_logManager.Sources.Clear();

				return;
			}

			if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
			{
				MessageBox.Show(this, "Неправильный путь.");
				return;
			}

			// создаем тестовый инструмент, на котором будет производится тестирование
            var _instrument = new Security
			{
				Id = "RIH2@RTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными
                Code = "RIH2",
				Name = "RTS-3.12",
				MinStepSize = 5,
				MinStepPrice = 2,
				Exchange = Exchange.Test,
			};

			// тестовый портфель
			var _portfolio = new Portfolio { Name = "test account", BeginAmount = 100000m };

			// хранилище, через которое будет производиться доступ к тиковой и котировочной базе
			var storage = new TradingStorage(new InMemoryStorage())
			{
				BasePath = HistoryPath.Text
			};

			var timeFrame = TimeSpan.FromMinutes(5);

			// в реальности период может быть другим, и это зависит от объема данных,
			// хранящихся по пути HistoryPath, 
			var startTime = new DateTime(2012, 20, 2);
			var stopTime = new DateTime(2012, 21, 2);
	
			_trader = new EmulationTrader(
                new[] { _instrument },
				new[] { _portfolio })
			{
				MarketTimeChangedInterval = timeFrame,
				Storage = storage,
				WorkingTime = Exchange.Rts.WorkingTime,

				// параметр влияет на занимаемую память.
				// в случае достаточно количества памяти на компьютере рекомендуется его увеличить
				DaysInMemory = 6,
			};

            _trader.DepthGenerators[_instrument] = new TrendMarketDepthGenerator(_instrument)
			{
				// стакан для инструмента в истории обновляется раз в секунду
				Interval = TimeSpan.FromSeconds(1),
			};

			var candleManager = new CandleManager();
			var builder = new CandleBuilder(new TradeCandleBuilderSource(_trader) { IsSyncProcess = true });
			candleManager.Sources.Add(builder);

			// в целях оптимизации расходования памяти храним не более 100 последних свечек и 100000 последних сделок
			((CandleContainer)candleManager.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxValueCount = 100000;

            candleManager.RegisterTimeFrameCandles(_instrument, timeFrame);

			// создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
            _strategy = new NewStrategy()
			{
				Volume = 1,
				Portfolio = _portfolio,
                Security = _instrument,
				Trader = _trader
			};

			// копируем параметры на визуальную панель
			ParametersPanel.Parameters.Clear();
			ParametersPanel.Parameters.AddRange(_strategy.EquityManager.Parameters);

			if (_curveItems == null)
				_curveItems = Curve.CreateCurve(_strategy.Name, Colors.DarkGreen);
			else
				_curveItems.Clear();

			_strategy.EquityManager.NewEquityData += data => this.GuiAsync(() => _curveItems.Add(data));

			_logManager.Sources.Add(_strategy);

			// и подписываемся на событие изменения времени, чтобы обновить ProgressBar
			_trader.MarketTimeChanged += () =>
			{
				// в целях оптимизации обновляем ProgressBar только при начале нового дня
				if (_trader.MarketTime.Date != _lastUpdateDate || _trader.MarketTime >= stopTime)
				{
					_lastUpdateDate = _trader.MarketTime.Date;
					this.GuiAsync(() => TestingProcess.Value = (_trader.MarketTime - startTime).Ticks);
				}
			};

			_trader.StateChanged += () =>
			{
				if (_trader.State == EmulationStates.Stopped)
				{
					this.GuiAsync(() =>
					{
						StartBtn.IsEnabled = true;

						if (TestingProcess.Value == TestingProcess.Maximum)
							MessageBox.Show("Закончено за " + (DateTime.Now - _startEmulationTime));
						else
							MessageBox.Show("Отменено");
					});
				}
				else if (_trader.State == EmulationStates.Started)
				{
					// запускаем стратегию когда эмулятор запустился
					_strategy.Start();
				}
			};

			// устанавливаем в визуальный элемент ProgressBar максимальное количество итераций)
			TestingProcess.Maximum = (stopTime - startTime).Ticks;
			TestingProcess.Value = 0;
			Report.IsEnabled = true;

			_startEmulationTime = DateTime.Now;

			// соединяемся с трейдером и запускаем экспорт,
			// чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader
			_trader.Connect();
			_trader.StartExport();

            /*------------------------------------------------------------*/
            _trader.RegisterQuotes(_instrument);

            _trader.QuotesChanged += depths =>
            {
                _marketDepth = depths.FirstOrDefault(d => d.Security == _instrument);
            };
            _trader.NewPositions += positions =>
            {
                if (_position == null)
                {
                    _position = positions.FirstOrDefault();
                }
            };

            _trader.NewOrders += myTrades =>
            {
                foreach (var myTrade in myTrades)
                {
                    var trade = myTrade;
                    int _pos = (int)trade.Direction;
                    if (posPrice == trade.Price && pos == _pos)
                    {
                        posId = trade.Id;
                    }
                }
            };
            /*------------------------------------------------------------*/

			// запускаем эмуляцию, задавая период тестирования (startTime, stopTime).
			_trader.Start(startTime, stopTime);
		}

		private void Report_Click(object sender, RoutedEventArgs e)
		{
			// сгерерировать отчет по прошедшему тестированию
			// Внимание! сделок и заявок может быть большое количество,
			// поэтому Excel отчет может тормозить
			new ExcelStrategyReport(_strategy, "sma.xls").Generate();

			// открыть отчет
			Process.Start("sma.xls");
		}
	}
}

1ое что я заметил, так это ```csharp var timeFrame = TimeSpan.FromMinutes(5);


2ое место, где я не знаю
```csharp
_trader.DepthGenerators[_instrument] = new TrendMarketDepthGenerator(_instrument)
			{
				// стакан для инструмента в истории обновляется раз в секунду
				Interval = TimeSpan.FromSeconds(1),
			};

как соб-но стакан в истории может обновляться раз в сек, если у меня история стаканов...

Подскажите пожалуйста)))

OvcharenkoVI
OvcharenkoVI
  1. Если не используете свечи, а по сделкам, то в принципе без разницы. Есть разница только какое StrategyRule использовать. В вашем случае MarketDepthChanged.

2.У вас прям вся история стакана? В тестировании стакан генерируется сам, вот вы и задаете частоту, с какой он будет обновляться

tmt
tmt Author

OvcharenkoVI:

  1. Если не используете свечи, а по сделкам, то в принципе без разницы. Есть разница только какое StrategyRule использовать. В вашем случае MarketDepthChanged.

2.У вас прям вся история стакана? В тестировании стакан генерируется сам, вот вы и задаете частоту, с какой он будет обновляться

те var timeFrame = TimeSpan.FromMinutes(5); вовсе убрать могу

Да вроде как вся(я за сутки хочу прогнать, тк у меня нету еще истории за месяц и более)

Залил истоию + прогу. http://zalil.ru/32853166 пароль "stocksharp" Ошибка сейчас, прикпрепил скрин

tmt
tmt Author

Решил начать с малого, сначало просто добиться открытия позиции в 1 сторону в OnStarting() и получился у меня вот такой код

MainWindow

namespace SampleHistoryTesting
{
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.IO;
	using System.Windows;
	using System.Windows.Forms;
	using System.Windows.Media;
	using MessageBox = System.Windows.MessageBox;

	using Ecng.Common;
	using Ecng.Serialization;
	using Ecng.Xaml;
	using Ecng.Collections;

	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Reporting;
	using StockSharp.Algo.Storages;
	using StockSharp.Algo.Strategies;
	using StockSharp.Algo.Testing;
	using StockSharp.Algo.Logging;
	using StockSharp.Algo.Equity;
	using StockSharp.Algo.Indicators.Trend;
	using StockSharp.BusinessEntities;
	
	public partial class MainWindow
	{
		private Strategy _strategy;

		private ICollection<EquityData> _curveItems;
		private EmulationTrader _trader;

		private readonly LogManager _logManager = new LogManager();

		private DateTime _lastUpdateDate;
		private DateTime _startEmulationTime;

		public MainWindow()
		{
			InitializeComponent();

			_logManager.Listeners.Add(new FileLogListener("log.txt"));
		}

		private void FindPath_Click(object sender, RoutedEventArgs e)
		{
			var dlg = new FolderBrowserDialog();

			if (!HistoryPath.Text.IsEmpty())
				dlg.SelectedPath = HistoryPath.Text;

			if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				HistoryPath.Text = dlg.SelectedPath;
			}
		}

		private void StartBtn_Click(object sender, RoutedEventArgs e)
		{
			// если процесс был запущен, то его останавливаем
			if (_trader != null && _trader.State != EmulationStates.Stopped)
			{
				StartBtn.IsEnabled = false;

				_strategy.Stop();
				_trader.Stop();
				_logManager.Sources.Clear();

				return;
			}

			if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
			{
				MessageBox.Show(this, "Неправильный путь.");
				return;
			}

			// создаем тестовый инструмент, на котором будет производится тестирование
			var security = new Security
			{
				Id = "RIH2@RTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными
                Code = "RIH2",
				Name = "RTS-3.12",
				MinStepSize = 5,
				MinStepPrice = 3,
				Exchange = Exchange.Test,
			};

			// тестовый портфель
			var portfolio = new Portfolio { Name = "test account", BeginAmount = 1000000m };

			// хранилище, через которое будет производиться доступ к тиковой и котировочной базе
			var storage = new TradingStorage(new InMemoryStorage())
			{
				BasePath = HistoryPath.Text
			};

			// в реальности период может быть другим, и это зависит от объема данных,
			// хранящихся по пути HistoryPath, 
            var startTime = new DateTime(2012, 2, 26);
            var stopTime = new DateTime(2012, 2, 27);
	
			_trader = new EmulationTrader(
				new[] { security },
				new[] { portfolio })
			{
				Storage = storage,
				WorkingTime = Exchange.Rts.WorkingTime,

				// параметр влияет на занимаемую память.
				// в случае достаточно количества памяти на компьютере рекомендуется его увеличить
				DaysInMemory = 6,
			};
			
			_trader.DepthGenerators[security] = new TrendMarketDepthGenerator(security)
			{
				// стакан для инструмента в истории обновляется раз в секунду
				Interval = TimeSpan.FromSeconds(1),
			};
            
			var candleManager = new CandleManager();
			var builder = new CandleBuilder(new TradeCandleBuilderSource(_trader) { IsSyncProcess = true });
			candleManager.Sources.Add(builder);

			// в целях оптимизации расходования памяти храним не более 100 последних свечек и 100000 последних сделок
			((CandleContainer)candleManager.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxValueCount = 100000;

			// создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
			_strategy = new NewStrategy()
			{
				Volume = 1,
				Portfolio = portfolio,
				Security = security,
				Trader = _trader
			};

			// копируем параметры на визуальную панель
			ParametersPanel.Parameters.Clear();
			ParametersPanel.Parameters.AddRange(_strategy.EquityManager.Parameters);

			if (_curveItems == null)
				_curveItems = Curve.CreateCurve(_strategy.Name, Colors.DarkGreen);
			else
				_curveItems.Clear();

			_strategy.EquityManager.NewEquityData += data => this.GuiAsync(() => _curveItems.Add(data));

			_logManager.Sources.Add(_strategy);

			// и подписываемся на событие изменения времени, чтобы обновить ProgressBar
			_trader.MarketTimeChanged += () =>
			{
				// в целях оптимизации обновляем ProgressBar только при начале нового дня
				if (_trader.MarketTime.Date != _lastUpdateDate || _trader.MarketTime >= stopTime)
				{
					_lastUpdateDate = _trader.MarketTime.Date;
					this.GuiAsync(() => TestingProcess.Value = (_trader.MarketTime - startTime).Ticks);
				}
			};

			_trader.StateChanged += () =>
			{
				if (_trader.State == EmulationStates.Stopped)
				{
					this.GuiAsync(() =>
					{
						StartBtn.IsEnabled = true;

						if (TestingProcess.Value == TestingProcess.Maximum)
							MessageBox.Show("Закончено за " + (DateTime.Now - _startEmulationTime));
						else
							MessageBox.Show("Отменено");
					});
				}
				else if (_trader.State == EmulationStates.Started)
				{
					// запускаем стратегию когда эмулятор запустился
					_strategy.Start();
				}
			};

			// устанавливаем в визуальный элемент ProgressBar максимальное количество итераций)
			TestingProcess.Maximum = (stopTime - startTime).Ticks;
			TestingProcess.Value = 0;
			Report.IsEnabled = true;

			_startEmulationTime = DateTime.Now;

			// соединяемся с трейдером и запускаем экспорт,
			// чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader
			_trader.Connect();
			_trader.StartExport();

			// запускаем эмуляцию, задавая период тестирования (startTime, stopTime).
			_trader.Start(startTime, stopTime);
		}

		private void Report_Click(object sender, RoutedEventArgs e)
		{
			// сгерерировать отчет по прошедшему тестированию
			// Внимание! сделок и заявок может быть большое количество,
			// поэтому Excel отчет может тормозить
			new ExcelStrategyReport(_strategy, "sma.xls").Generate();

			// открыть отчет
			Process.Start("sma.xls");
		}
	}
}

и код стратегии

namespace SampleHistoryTesting
{
	using System;

	using StockSharp.Algo;
	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Indicators;
	using StockSharp.Algo.Indicators.Trend;
	using StockSharp.Algo.Strategies;
	using StockSharp.BusinessEntities;

	class NewStrategy : Strategy
	{
		protected override void OnStarting()
		{
			sell();

			base.OnStarting();
		}

        public void sell()
		{
            var order = this.CreateOrder(OrderDirections.Sell, Security.GetMarketPrice(OrderDirections.Sell), Volume);
            RegisterOrder(order);
		}
	}
}

Ну и в общем цена не может быть равна 0 у order.. Как я понял у меня вообще ни 1 цены нету.. Скрины ниже

И кстати, это уже 4,0,21 версия (все что выше я пробовал на 20)

vader
vader

Выведете, чему равна цена ,по которой ставите заявку.

tmt
tmt Author

vader: Выведете, чему равна цена ,по которой ставите заявку. из второй картинки видно же, что значение null

tmt
tmt Author

Сделал вот так

namespace SampleHistoryTesting
{
	using System;

	using StockSharp.Algo;
	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Indicators;
	using StockSharp.Algo.Indicators.Trend;
	using StockSharp.Algo.Strategies;
	using StockSharp.BusinessEntities;

    using MessageBox = System.Windows.MessageBox;

	class NewStrategy : Strategy
	{
		protected override void OnStarting()
		{
			sell();

			base.OnStarting();
		}

        public void sell()
		{
            MessageBox.Show("цена " + Security.BestAsk.Price);
            
                // MessageBox.Show(Security.BestAsk.Price);
            /*var order = new Order
            {
                Portfolio = Portfolio,
                Price = Security.BestAsk.Price,
                Security = Security,
                Volume = 1,
                Direction = OrderDirections.Sell
            };
            RegisterOrder(order);*/
		}
	}
}

Получаю вот это (скрин внизу)

Как раз на MessageBox.Show("цена " + Security.BestAsk.Price);

vader
vader

Вторая картинка у меня не открывалась.

Alexander
Alexander

Очевидно что ошибка из-за того что BestAsk = null

tmt
tmt Author

Alexander Mukhanchikov: Очевидно что ошибка из-за того что BestAsk = null ну это я понял, но что я не так делаю, что стакан получить не могу?

Alexander
Alexander

tmt:

Alexander Mukhanchikov: Очевидно что ошибка из-за того что BestAsk = null ну это я понял, но что я не так делаю, что стакан получить не могу?

Не запускаете экспорт стакана. Читайте документацию внимательнее.

tmt
tmt Author
			_trader.Connect();
			_trader.StartExport();

            _trader.RegisterQuotes(security);

Вот запуск экспорта стакана, после _trader.StartExport();

Alexander
Alexander

А экспорт успевает запуститься? Может стоит хотя бы проверку вставить да, к примеру, каждый вызов OnProcess в TimeFrame стратегии проверять стакан?

tmt
tmt Author

Alexander Mukhanchikov: А экспорт успевает запуститься? Может стоит хотя бы проверку вставить да, к примеру, каждый вызов OnProcess в TimeFrame стратегии проверять стакан? А как проверить, успевает или нет?

Alexander
Alexander

У вас не успевает, могу вам сразу сказать. Раз бид = null

Я вам всячески рекомендую либо записаться к нам на курсы, либо воспользоваться услугой поддержки. А то так можно очень долго выяснять подобные мелочи, и в итоге на каком-то шаге сдаться, потратив слишком много времени и сил впустую.

tmt
tmt Author

Alexander Mukhanchikov: У вас не успевает, могу вам сразу сказать. Раз бид = null

Я вам всячески рекомендую либо записаться к нам на курсы, либо воспользоваться услугой поддержки. А то так можно очень долго выяснять подобные мелочи, и в итоге на каком-то шаге сдаться, потратив слишком много времени и сил впустую. А сколько экспорт стакана запускается? может задержку сделать после запуска. Я бы с радостью заплатить за поддержку, но в бюджете брешь на данный момент😀

Alexander
Alexander

Вариант как сделать я вам написал выше. Выше дело принимать его или делать по-своему.

tmt
tmt Author

Экспорт стакана надо запустить перед запуском эмуляции или после? И если перед, то проверку перед запуском проводить? а после уже запускать.. или как?

Ответьте пожалуйста, спасибо

tmt
tmt Author

Сделал вот так.. Все равно не получается, стакан не появляется ((((

Добавил событие появления новых инструментов и выяснил что они появляются сразу, без запуска эмуляции

            _trader.NewSecurities += sec =>
            {
                _trader.GetMarketDepth(security);
            };
  • добавил событие изменения стакана.. По которому и стартуется стратегия, но вот это событие не срабатывает...
bool str = false;

            _trader.QuotesChanged += depths =>
            {
                if (str == false)
				{
                    str = true;
                    _strategy.Start();
                }
                _marketDepth = depths.FirstOrDefault(d => d.Security == security);
            };

Может где баг какой?

namespace SampleHistoryTesting
{
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.IO;
	using System.Windows;
	using System.Windows.Forms;
	using System.Windows.Media;
	using MessageBox = System.Windows.MessageBox;

	using Ecng.Common;
	using Ecng.Serialization;
	using Ecng.Xaml;
	using Ecng.Collections;

	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Reporting;
	using StockSharp.Algo.Storages;
	using StockSharp.Algo.Strategies;
	using StockSharp.Algo.Testing;
	using StockSharp.Algo.Logging;
	using StockSharp.Algo.Equity;
	using StockSharp.Algo.Indicators.Trend;
	using StockSharp.BusinessEntities;

    using System.Linq;

    using System.Threading;
	
	public partial class MainWindow
	{
		private Strategy _strategy;

		private ICollection<EquityData> _curveItems;
		private EmulationTrader _trader;

		private readonly LogManager _logManager = new LogManager();

		private DateTime _lastUpdateDate;
		private DateTime _startEmulationTime;
        public static MarketDepth _marketDepth;
        //public Security security;

		public MainWindow()
		{
			InitializeComponent();

			_logManager.Listeners.Add(new FileLogListener("log.txt"));
		}

		private void FindPath_Click(object sender, RoutedEventArgs e)
		{
			var dlg = new FolderBrowserDialog();

			if (!HistoryPath.Text.IsEmpty())
				dlg.SelectedPath = HistoryPath.Text;

			if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				HistoryPath.Text = dlg.SelectedPath;
			}
		}

		private void StartBtn_Click(object sender, RoutedEventArgs e)
		{
			// если процесс был запущен, то его останавливаем
			if (_trader != null && _trader.State != EmulationStates.Stopped)
			{
				StartBtn.IsEnabled = false;

				_strategy.Stop();
				_trader.Stop();
				_logManager.Sources.Clear();

				return;
			}

			if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
			{
				MessageBox.Show(this, "Неправильный путь.");
				return;
			}

			// создаем тестовый инструмент, на котором будет производится тестирование
            var security = new Security
			{
				Id = "RIH2@RTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными
                Code = "RIH2",
				Name = "RTS-3.12",
				MinStepSize = 5,
				MinStepPrice = 3,
				Exchange = Exchange.Rts,
			};

			// тестовый портфель
			var portfolio = new Portfolio { Name = "test account", BeginAmount = 1000000m };

			// хранилище, через которое будет производиться доступ к тиковой и котировочной базе
			var storage = new TradingStorage(new InMemoryStorage())
			{
				BasePath = HistoryPath.Text
			};

			// в реальности период может быть другим, и это зависит от объема данных,
			// хранящихся по пути HistoryPath, 
            var startTime = new DateTime(2012, 2, 26);
            var stopTime = new DateTime(2012, 2, 27);
	
			_trader = new EmulationTrader(
				new[] { security },
				new[] { portfolio })
			{
				Storage = storage,
				WorkingTime = Exchange.Rts.WorkingTime,

				// параметр влияет на занимаемую память.
				// в случае достаточно количества памяти на компьютере рекомендуется его увеличить
				DaysInMemory = 6,
			};

            _trader.DepthGenerators[security] = new TrendMarketDepthGenerator(security);
            
			var candleManager = new CandleManager();
			var builder = new CandleBuilder(new TradeCandleBuilderSource(_trader) { IsSyncProcess = true });
			candleManager.Sources.Add(builder);

			// в целях оптимизации расходования памяти храним не более 100 последних свечек и 100000 последних сделок
			((CandleContainer)candleManager.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxValueCount = 100000;

			// создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
			_strategy = new NewStrategy()
			{
				Volume = 1,
				Portfolio = portfolio,
				Security = security,
				Trader = _trader
			};

			// копируем параметры на визуальную панель
			ParametersPanel.Parameters.Clear();
			ParametersPanel.Parameters.AddRange(_strategy.EquityManager.Parameters);

			if (_curveItems == null)
				_curveItems = Curve.CreateCurve(_strategy.Name, Colors.DarkGreen);
			else
				_curveItems.Clear();

			_strategy.EquityManager.NewEquityData += data => this.GuiAsync(() => _curveItems.Add(data));

			_logManager.Sources.Add(_strategy);

			// и подписываемся на событие изменения времени, чтобы обновить ProgressBar
			_trader.MarketTimeChanged += () =>
			{
				// в целях оптимизации обновляем ProgressBar только при начале нового дня
				if (_trader.MarketTime.Date != _lastUpdateDate || _trader.MarketTime >= stopTime)
				{
					_lastUpdateDate = _trader.MarketTime.Date;
					this.GuiAsync(() => TestingProcess.Value = (_trader.MarketTime - startTime).Ticks);
				}
			};

			_trader.StateChanged += () =>
			{
				if (_trader.State == EmulationStates.Stopped)
				{
					this.GuiAsync(() =>
					{
						StartBtn.IsEnabled = true;

						if (TestingProcess.Value == TestingProcess.Maximum)
							MessageBox.Show("Закончено за " + (DateTime.Now - _startEmulationTime));
						else
							MessageBox.Show("Отменено");
					});
				}
				else if (_trader.State == EmulationStates.Started)
				{
					// запускаем стратегию когда эмулятор запустился
                    //_strategy.Start();
				}
			};

            bool str = false;

            _trader.QuotesChanged += depths =>
            {
                if (str == false)
				{
                    str = true;
                    _strategy.Start();
                }
                _marketDepth = depths.FirstOrDefault(d => d.Security == security);
            };

            _trader.NewSecurities += sec =>
            {
                _trader.GetMarketDepth(security);
            };

			// устанавливаем в визуальный элемент ProgressBar максимальное количество итераций)
			TestingProcess.Maximum = (stopTime - startTime).Ticks;
			TestingProcess.Value = 0;
			Report.IsEnabled = true;

			_startEmulationTime = DateTime.Now;

			// соединяемся с трейдером и запускаем экспорт,
			// чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader
			_trader.Connect();
			_trader.StartExport();

            

			// запускаем эмуляцию, задавая период тестирования (startTime, stopTime).
			_trader.Start(startTime, stopTime);
		}

		private void Report_Click(object sender, RoutedEventArgs e)
		{
			// сгерерировать отчет по прошедшему тестированию
			// Внимание! сделок и заявок может быть большое количество,
			// поэтому Excel отчет может тормозить
			new ExcelStrategyReport(_strategy, "sma.xls").Generate();

			// открыть отчет
			Process.Start("sma.xls");
		}
	}
}
tmt
tmt Author

_trader.QuotesChanged ни разу не срабатывает.. Стратегия даже не запускается и следовательно стакан = null.. Попробую на какой нить старой версии, может заработает

Увы, но с QuotesChanged тоже самое на 3.1, похоже у меня руки кривые 😀 выложите кто нибудь рабочий пример со стаканом пожалуйста😳

Alexander
Alexander

Смотрите примеры из архива

Moadip
Moadip

выложите кто нибудь рабочий пример со стаканом пожалуйста

Взял оригинальный SampleHistoryTesting, заменил в нем SmaStrategy на вашу стратегию - NewStrategy

Поменял инструмент и дату тестирования


// создаем тестовый инструмент, на котором будет производится тестирование
var security = new Security
{
	Id = "RIM2@RTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными
	Code = "RIM2",
	Name = "RTS-6.12",
	MinStepSize = 5,
	MinStepPrice = 2,
	Exchange = Exchange.Test,
};

 ...

var startTime = new DateTime(2012, 3, 16);
var stopTime = new DateTime(2012, 3, 17);


Поставил обновление стакана раз в 10 сек. т.к. при 1 сек. тестер перешел в пошаговый режим.😀


_trader.DepthGenerators[security] = new TrendMarketDepthGenerator(security)
{
	// стакан для инструмента в истории обновляется раз в секунду
	Interval = TimeSpan.FromSeconds(10),
};

Подправил создание стратегии


// создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
_strategy = new NewStrategy()
{
	Volume = 1,
	Portfolio = portfolio,
	Security = security,
	Trader = _trader
};

Больше ничего не менял. Пуск!

До конца теста ждать не стал.

Полный код на на всякий случай


namespace SampleHistoryTesting
{
	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.IO;
	using System.Windows;
	using System.Windows.Forms;
	using System.Windows.Media;
	using MessageBox = System.Windows.MessageBox;

	using Ecng.Common;
	using Ecng.Serialization;
	using Ecng.Xaml;
	using Ecng.Collections;

	using StockSharp.Algo.Candles;
	using StockSharp.Algo.Reporting;
	using StockSharp.Algo.Storages;
	using StockSharp.Algo.Strategies;
	using StockSharp.Algo.Testing;
	using StockSharp.Algo.Logging;
	using StockSharp.Algo.Equity;
	using StockSharp.Algo.Indicators.Trend;
	using StockSharp.BusinessEntities;
	
	public partial class MainWindow
	{
		private Strategy _strategy;

		private ICollection<EquityData> _curveItems;
		private EmulationTrader _trader;

		private readonly LogManager _logManager = new LogManager();

		private DateTime _lastUpdateDate;
		private DateTime _startEmulationTime;

		public MainWindow()
		{
			InitializeComponent();

			_logManager.Listeners.Add(new FileLogListener("log.txt"));
		}

		private void FindPath_Click(object sender, RoutedEventArgs e)
		{
			var dlg = new FolderBrowserDialog();

			if (!HistoryPath.Text.IsEmpty())
				dlg.SelectedPath = HistoryPath.Text;

			if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
			{
				HistoryPath.Text = dlg.SelectedPath;
			}
		}

		private void StartBtn_Click(object sender, RoutedEventArgs e)
		{
			// если процесс был запущен, то его останавливаем
			if (_trader != null && _trader.State != EmulationStates.Stopped)
			{
				StartBtn.IsEnabled = false;

				_strategy.Stop();
				_trader.Stop();
				_logManager.Sources.Clear();

				return;
			}

			if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
			{
				MessageBox.Show(this, "Неправильный путь.");
				return;
			}

			// создаем тестовый инструмент, на котором будет производится тестирование
			var security = new Security
			{
				Id = "RIM2@RTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными
				Code = "RIM2",
				Name = "RTS-6.12",
				MinStepSize = 5,
				MinStepPrice = 2,
				Exchange = Exchange.Test,
			};

			// тестовый портфель
			var portfolio = new Portfolio { Name = "test account", BeginAmount = 1000000m };

			// хранилище, через которое будет производиться доступ к тиковой и котировочной базе
			var storage = new TradingStorage(new InMemoryStorage())
			{
				BasePath = HistoryPath.Text
			};

			var timeFrame = TimeSpan.FromMinutes(5);

			// в реальности период может быть другим, и это зависит от объема данных,
			// хранящихся по пути HistoryPath, 
			var startTime = new DateTime(2012, 3, 16);
			var stopTime = new DateTime(2012, 3, 17);
	
			_trader = new EmulationTrader(
				new[] { security },
				new[] { portfolio })
			{
				MarketTimeChangedInterval = timeFrame,
				Storage = storage,
				WorkingTime = Exchange.Rts.WorkingTime,

				// параметр влияет на занимаемую память.
				// в случае достаточно количества памяти на компьютере рекомендуется его увеличить
				DaysInMemory = 6,
			};
			
			_trader.DepthGenerators[security] = new TrendMarketDepthGenerator(security)
			{
				// стакан для инструмента в истории обновляется раз в секунду
				Interval = TimeSpan.FromSeconds(10),
			};

			var candleManager = new CandleManager();
			var builder = new CandleBuilder(new TradeCandleBuilderSource(_trader) { IsSyncProcess = true });
			candleManager.Sources.Add(builder);

			// в целях оптимизации расходования памяти храним не более 100 последних свечек и 100000 последних сделок
			((CandleContainer)candleManager.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxCandleCount = 100;
			((CandleBuilderContainer)builder.Container).MaxValueCount = 100000;

			candleManager.RegisterTimeFrameCandles(security, timeFrame);

			// создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток
            _strategy = new NewStrategy()
			{
				Volume = 1,
				Portfolio = portfolio,
				Security = security,
				Trader = _trader
			};

			// копируем параметры на визуальную панель
			ParametersPanel.Parameters.Clear();
			ParametersPanel.Parameters.AddRange(_strategy.EquityManager.Parameters);

			if (_curveItems == null)
				_curveItems = Curve.CreateCurve(_strategy.Name, Colors.DarkGreen);
			else
				_curveItems.Clear();

			_strategy.EquityManager.NewEquityData += data => this.GuiAsync(() => _curveItems.Add(data));

			_logManager.Sources.Add(_strategy);

			// и подписываемся на событие изменения времени, чтобы обновить ProgressBar
			_trader.MarketTimeChanged += () =>
			{
				// в целях оптимизации обновляем ProgressBar только при начале нового дня
				if (_trader.MarketTime.Date != _lastUpdateDate || _trader.MarketTime >= stopTime)
				{
					_lastUpdateDate = _trader.MarketTime.Date;
					this.GuiAsync(() => TestingProcess.Value = (_trader.MarketTime - startTime).Ticks);
				}
			};

			_trader.StateChanged += () =>
			{
				if (_trader.State == EmulationStates.Stopped)
				{
					this.GuiAsync(() =>
					{
						StartBtn.IsEnabled = true;

						if (TestingProcess.Value == TestingProcess.Maximum)
							MessageBox.Show("Закончено за " + (DateTime.Now - _startEmulationTime));
						else
							MessageBox.Show("Отменено");
					});
				}
				else if (_trader.State == EmulationStates.Started)
				{
					// запускаем стратегию когда эмулятор запустился
					_strategy.Start();
				}
			};

			// устанавливаем в визуальный элемент ProgressBar максимальное количество итераций)
			TestingProcess.Maximum = (stopTime - startTime).Ticks;
			TestingProcess.Value = 0;
			Report.IsEnabled = true;

			_startEmulationTime = DateTime.Now;

			// соединяемся с трейдером и запускаем экспорт,
			// чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader
			_trader.Connect();
			_trader.StartExport();

			// запускаем эмуляцию, задавая период тестирования (startTime, stopTime).
			_trader.Start(startTime, stopTime);
		}

		private void Report_Click(object sender, RoutedEventArgs e)
		{
			// сгерерировать отчет по прошедшему тестированию
			// Внимание! сделок и заявок может быть большое количество,
			// поэтому Excel отчет может тормозить
			new ExcelStrategyReport(_strategy, "sma.xls").Generate();

			// открыть отчет
			Process.Start("sma.xls");
		}
	}
}

tmt
tmt Author

Ошибка моя была в том, что я указывал путь до папки RIH2@RTS, а не той, в которой лежит RIH2@RTS... 2е недели пытался понять, что такое у меня с кодом...😀