Доброго всем дня, особенно Михаилу :).
Начал осваивать событийный подход, забуксовал.
Подскажите, пожалуйста, как правильно запускать стратегию наподобие той,
что приведена в примере (class MyOwnStrategy : ActionStrategy)?
Нужно ли добавлять в нее конструктор и отдельно передавать Security?
Сейчас запускаю на ФОРТС так:
Code_strategy = new MyOwnStrategy() { Volume = 1 };
_manager.Register(_strategy, this.Portfolios.SelectedPortfolio, _rts);
if (_strategy.ProcessState == StrategyProcessStates.Stopped)
{
_strategy.Start();
}
else
{
_strategy.Stop();
}
Стратегия нормально запускается и останавливается из GUI примера SampleSMA, лог пишется, но сделок не происходит на любом таймфрейме.
Лог обычно такой:
MOS 20:34:52.0212958 Стратегия запущена.
MOS 20:36:11.3213772 Стратегия останавливается.
MOS 20:36:11.6273947 Стратегия остановлена.
Событийную стратегию взял из мануала, без изменений, версия 3.0.
Буду признателен за помощь.
Весь запускающий код, кроме самой стратегии из примера:
Codenamespace SampleSMA
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using MessageBox = System.Windows.MessageBox;
using AmCharts.Windows.Stock;
using Ecng.Collections;
using Ecng.Common;
using Ecng.ComponentModel;
using Ecng.Trading.Algo;
using Ecng.Trading.Algo.Candles;
using Ecng.Trading.Algo.Logging;
using Ecng.Trading.Algo.Reporting;
using Ecng.Trading.Algo.Strategies;
using Ecng.Trading.BusinessEntities;
using Ecng.Trading.Quik;
using Ecng.Trading.Xaml;
using Ecng.Xaml;
public partial class MainWindow
{
private readonly TimeSpan _timeFrame = TimeSpan.FromMinutes(1);
private QuikTrader _trader;
private MyOwnStrategy _strategy;
private RealTimeStrategyManager _manager;
private bool _isDdeStarted;
private Security _rts;
public CandleManager _candleManager;
public MainWindow()
{
InitializeComponent();
// изменяет текущий формат, чтобы нецелое числа интерпритировалось как разделенное точкой.
var cci = new CultureInfo(Thread.CurrentThread.CurrentCulture.Name) { NumberFormat = { NumberDecimalSeparator = "." } };
Thread.CurrentThread.CurrentCulture = cci;
}
private void _orders_OrderSelected(object sender, EventArgs e)
{
this.CancelOrders.IsEnabled = _orders.SelectedOrders.Count() > 0;
}
protected override void OnClosing(CancelEventArgs e)
{
if (_trader != null)
{
_manager.Dispose();
if (_isDdeStarted)
StopDde();
_trader.Dispose();
}
base.OnClosing(e);
}
private void FindPath_Click(object sender, RoutedEventArgs e)
{
var dlg = new FolderBrowserDialog();
if (!this.Path.Text.IsEmpty())
dlg.SelectedPath = this.Path.Text;
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
this.Path.Text = dlg.SelectedPath;
}
}
private void Connect_Click(object sender, RoutedEventArgs e)
{
if (_trader == null || !_trader.IsConnected)
{
if (_trader == null)
{
if (this.Path.Text.IsEmpty())
{
MessageBox.Show(this, "Путь к Quik не выбран.");
return;
}
// создаем шлюз
_trader = new QuikTrader(this.Path.Text);
// создаем менеджер стратегий
_manager = new RealTimeStrategyManager(_trader);
this.Portfolios.Trader = _trader;
_trader.Connected += () =>
{
_candleManager = new CandleManager(_trader);
_trader.NewSecurities += securities => this.GuiAsync(() =>
{
// находим нужную бумагу
var rts = securities.FirstOrDefault(s => s.Code == "RIM1");
if (rts != null)
{
_rts = rts;
this.GuiAsync(() =>
{
this.Start.IsEnabled = true;
});
}
});
_trader.ConnectionError += ex =>
{
if (ex != null)
this.GuiAsync(() => MessageBox.Show(this, ex.ToString()));
};
this.GuiAsync(() =>
{
this.ConnectBtn.IsEnabled = false;
this.ExportDde.IsEnabled = true;
this.Report.IsEnabled = true;
});
};
}
_trader.Connect();
}
else
_trader.Disconnect();
}
private void OnNewOrder(Order order)
{
_orders.Orders.Add(order);
this.GuiAsync(() => _chart.Orders.Add(order));
}
private void OnLog(Strategy strategy, StrategyErrorStates errorState, string message)
{
// если стратегия вывела не просто сообщение, то вывести на экран.
if (errorState != StrategyErrorStates.None)
this.GuiAsync(() => MessageBox.Show(this, message));
}
private void OnStrategyPropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.GuiAsync(() =>
{
this.Status.Content = _strategy.ProcessState;
this.PnL.Content = _strategy.PnLManager.PnL;
this.Slippage.Content = _strategy.SlippageManager.Slippage;
this.Position.Content = _strategy.PositionManager.Position;
this.Latency.Content = _strategy.LatencyManager.Latency;
});
}
private void StartDde()
{
_trader.StartExport();
_isDdeStarted = true;
}
private void StopDde()
{
_trader.StopExport();
_isDdeStarted = false;
}
private void ExportDde_Click(object sender, RoutedEventArgs e)
{
if (_isDdeStarted)
StopDde();
else
StartDde();
}
private void CancelOrders_Click(object sender, RoutedEventArgs e)
{
_orders.SelectedOrders.ForEach(_trader.CancelOrder);
}
private void Start_Click(object sender, RoutedEventArgs e)
{
if (_strategy == null)
{
if (this.Portfolios.SelectedPortfolio == null)
{
MessageBox.Show(this, "Портфель не выбран.");
return;
}
// создаем стратегию
_strategy = new MyOwnStrategy() { Volume = 1 };
_strategy.Log += OnLog;
_strategy.NewOrder += OnNewOrder;
_strategy.PropertyChanged += OnStrategyPropertyChanged;
// регистрируем стратегию, чтобы она начала обрабатываться
_manager.Register(_strategy, this.Portfolios.SelectedPortfolio, _rts);
var fileLogger = new FileStrategyLogger("{0}_{1:00}_{2:00}.txt".Put(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day));
fileLogger.Strategies.Add(_strategy);
this.Report.IsEnabled = true;
}
if (_strategy.ProcessState == StrategyProcessStates.Stopped)
{
_strategy.Start();
this.Start.Content = "Хватит";
}
else
{
_strategy.Stop();
this.Start.Content = "Понеслась";
}
}
private void Report_Click(object sender, RoutedEventArgs e)
{
var fileName = "report_{0}_{1}.xls".Put(_strategy.Security.Code, DateTime.Now.ToString("yyyy_MM_dd_HH_mm"));
new ExcelStrategyReport(_strategy, System.IO.Path.Combine(Directory.GetCurrentDirectory(), fileName)).Generate();
}
}
}