VassilSanych
|
Дата: 21.02.2013
kahuna события изменения состояния не вызываются, На слух как-то плохо воспринимается.
|
|
Спасибо:
|
|
|
|
|
kahuna
|
Дата: 22.02.2013
например событие strategy.OrderChanged. И следующий код никогда не исполняется (то что внутри цикла foreach) хотя ордера выставляются. Код
_trader.NewMyTrades += myTrades => this.GuiAsync(() =>
{
if (_strategy != null)
{
// найти те сделки, которые совершила стратегия
myTrades = myTrades.Where(t => _strategy.Orders.Any(o => o == t.Order));
_trades.Trades.AddRange(myTrades);
}
foreach (var myTrade in myTrades)
{
var trade = myTrade.Trade;
Status.Text = "Сделка {0} по цене {1} по бумаге {2} по объему {3} в {4}." +
System.Convert.ToString(trade.Id) + System.Convert.ToString(trade.Price) +
System.Convert.ToString(trade.Security.Code) +
System.Convert.ToString(trade.Volume) + System.Convert.ToString(trade.Time);
}
});
такое впечатление что у меня событийная модель не работает. Попробую сделать упрощеный тестовый примерчик.
|
|
Спасибо:
|
|
|
|
|
Moadip
|
Дата: 22.02.2013
Цитата:Когда переключаюсь с эмулятора на реальный QuikTrader. Что подразумевается под "переключением"? Как вы это делаете, опишите подробнее, желательно с примером кода.
|
|
Спасибо:
|
|
|
|
|
VassilSanych
|
Дата: 22.02.2013
kahuna _strategy.Orders.Any(o => o == t.Order)) Не уверен, что NewMyTrades и _strategy ссылаются на одни и те же экземпляры объектов заявок в памяти.
|
|
|
|
|
kahuna
|
Дата: 22.02.2013
|
|
|
|
Moadip Цитата:Когда переключаюсь с эмулятора на реальный QuikTrader. Что подразумевается под "переключением"? Как вы это делаете, опишите подробнее, желательно с примером кода. Если оставляю #define EMULATOR сделки совершаются и событие стратегии OrderChanged срабатывает в лог попадает сообщение "состояние ордера изменилось". не показывает Status.Text = _strategy.ProcessState.ToString(); не показывает PnL.Content = _strategy.PnLManager.PnL; не показывает Slippage.Content = _strategy.SlippageManager.Slippage; показывает Position.Content = _strategy.PositionManager.Position;не показываетLatency.Content = _strategy.Latency; Если на реальном Quik (снят комментарий с #undef EMULATOR) то сделки совершаются но событие OrderChanged не срабатывает. не показывает Status.Text = _strategy.ProcessState.ToString(); не показывает PnL.Content = _strategy.PnLManager.PnL; не показывает Slippage.Content = _strategy.SlippageManager.Slippage; не показывает Position.Content = _strategy.PositionManager.Position; не показывает Latency.Content = _strategy.Latency; Основной код: Код
#define EMULATOR
//#undef EMULATOR
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using MessageBox = System.Windows.MessageBox;
using System.Threading;
using System.Linq;
using System.Xml;
using Xceed.Wpf.Toolkit;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Xaml;
using Ecng.ComponentModel;
using StockSharp.BusinessEntities;
using StockSharp.Algo.Reporting;
using StockSharp.Quik;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Xaml;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Indicators.Trend;
using StockSharp.Logging;
using StockSharp.Algo.Testing;
namespace tryBot1
{
/// <summary>
/// Логика взаимодействия для MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ConfigFile CfgFile;
#if EMULATOR
private RealTimeEmulationTrader<QuikTrader> _trader;
#else
private QuikTrader _trader;
#endif
public static MarketDepth _depth;
private tryStrategy _strategy;
private bool _isDdeStarted;
private MonitorWindow monitor;
private LogManager _logManager;
public static bool tryBuy = false;
public static bool trySell = false;
public MainWindow()
{
InitializeComponent();
CfgFile = new ConfigFile("c:\\tryBot1\\","config.cfg");
monitor = new MonitorWindow();
monitor.Show();
_logManager = new LogManager();
//var fileListener = new FileLogListener("{0}_{1:00}_{2:00}.txt".Put(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day));
//logManager.Listeners.Add(fileListener);
_logManager.Listeners.Add(new GuiLogListener(monitor));
}
private void Connect_Click(object sender, RoutedEventArgs e)
{
//устанвавливаем элемент ComboBox на значение по умолчанию
//прочитанное ранее из config.cnf
String DefSecurity = CfgFile.ReadParam("Security");
String DefPortfolio = CfgFile.ReadParam("Portfolio");
//КОНЕЦ- устанвавливаем элемент ComboBox на значение по умолчанию
//прочитанное ранее из config.cnf
int i = 0;
if (_trader == null || !_trader.IsConnected)
{
if (_trader == null)
{
if (QuikTerminal.GetDefaultPath().IsEmpty())
{
MessageBox.Show(this, "Путь к Quik не выбран.");
return;
}
Status.Text = "Connecting with Quck. Please wait";
#if EMULATOR
_trader = new RealTimeEmulationTrader<QuikTrader>(new QuikTrader(QuikTerminal.GetDefaultPath()));
#else
_trader = new QuikTrader(QuikTerminal.GetDefaultPath()){ IsAsyncMode = true, SupportManualOrders = false };
_trader.IsAsyncMode = true;
#endif
_trader.Connected += () =>
{
_trader.NewSecurities += securities => this.GuiAsync(() =>
{
Securities1.ItemsSource = _trader.Securities;
i = 0;
foreach (Object item in Securities1.Items)
{
Securities1.SelectedIndex = i;
if (item.ToString().Equals(DefSecurity))
{
break;
}
i++;
}
// если инструмент и стакан уже появились
if (Securities1.SelectedItem != null)
{
Status.Text = "Инструмент появился.";
}
});
_trader.NewPortfolios += portfolios => this.GuiAsync(() =>
{
Portfolios.ItemsSource = _trader.Portfolios;
i = 0;
foreach (Object item in Portfolios.Items)
{
Portfolios.SelectedIndex = i;
if (item.ToString().Equals(DefPortfolio))
{
break;
}
i++;
}
});
// подписываемся на событие появления моих новых сделок
_trader.NewMyTrades += myTrades => this.GuiAsync(() =>
{
if (_strategy != null)
{
// найти те сделки, которые совершила стратегия
myTrades = myTrades.Where(t => _strategy.Orders.Any(o => o == t.Order));
//_trades.Trades.AddRange(myTrades);
}
foreach (var myTrade in myTrades)
{
var trade = myTrade.Trade;
Status.Text = "Сделка {0} по цене {1} по бумаге {2} по объему {3} в {4}." + System.Convert.ToString(trade.Id) + System.Convert.ToString(trade.Price) +
System.Convert.ToString(trade.Security.Code) + System.Convert.ToString(trade.Volume) + System.Convert.ToString(trade.Time);
}
});
// подписываемся на событие обновления стакана
_trader.MarketDepthsChanged += depths => this.GuiAsync(() =>
{
if (_depth == null && Securities1.SelectedItem != null)
{
_depth = depths.FirstOrDefault(d => d.Security.Equals( (Security)Securities1.SelectedItem ));
while (_depth == null) ;
Status.Text = "Стакан появился.";
}
});
};//КОНЕЦ _trader.Conected
_trader.ConnectionError += ex =>
{
if (ex != null)
this.GuiAsync(() => MessageBox.Show(this, ex.ToString()));
};
this.GuiAsync(() =>
{
Connect.IsEnabled = false;
ExportDde.IsEnabled = true;
Report.IsEnabled = true;
});
// подписываемся на событие о неудачной регистрации заявок
this._trader.OrdersRegisterFailed += OrdersFailed;
// подписываемся на событие о неудачном снятии заявок
this._trader.OrdersCancelFailed += OrdersFailed;
// подписываемся на событие о неудачной регистрации стоп-заявок
this._trader.StopOrdersRegisterFailed += OrdersFailed;
// подписываемся на событие о неудачном снятии стоп-заявок
this._trader.StopOrdersCancelFailed += OrdersFailed;
// запускаем экспорт по DDE
_trader.Connect();
while (!_trader.IsConnected) { }
Status.Text = "Connected with Quik terminal";
StartDde();
#if EMULATOR
_trader.UnderlyingTrader.LogLevel = LogLevels.Debug;
_logManager.Sources.Add(_trader.UnderlyingTrader);
#else
_trader.LogLevel = LogLevels.Debug;
_logManager.Sources.Add(_trader);
#endif
}
else
_trader.Disconnect();
}
}
private void OrdersFailed(IEnumerable<OrderFail> fails)
{
this.GuiAsync(() =>
{
foreach (var fail in fails)
MessageBox.Show(this, fail.Error.ToString(), "Ошибка регистрации заявки");
});
}
private void StartDde()
{
_trader.StartExport();
_isDdeStarted = true;
}
private void StopDde()
{
_trader.StopExport();
_isDdeStarted = false;
}
private void OnStrategyPropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.GuiAsync(() =>
{
//Status.Content = _strategy.ProcessState;
Status.Text = _strategy.ProcessState.ToString();
PnL.Content = _strategy.PnLManager.PnL;
Slippage.Content = _strategy.SlippageManager.Slippage;
Position.Content = _strategy.PositionManager.Position;
Latency.Content = _strategy.Latency;
});
}
private void SwitchOn_Click(object sender, RoutedEventArgs e)
{
if (_strategy == null )
{
// создаем торговую стратегию,
_strategy = new tryStrategy()
{
Volume = 1,
Security = (Security)Securities1.SelectedItem,
Portfolio = (Portfolio)Portfolios.SelectedItem,
Trader = _trader
};
_strategy.PropertyChanged += OnStrategyPropertyChanged;
_logManager.Sources.Add(_strategy);
if (_strategy.ProcessState == ProcessStates.Stopped)
{
// запускаем процесс получения стакана, необходимый для работы алгоритма котирования
_trader.RegisterMarketDepth(_strategy.Security);
_strategy.Start();
Status.Text = "Старт";
}
else
{
_trader.UnRegisterMarketDepth(_strategy.Security);
_strategy.Stop();
Status.Text = "Стоп";
}
}
}
private void ExportDde_Click(object sender, RoutedEventArgs e)
{
if (_isDdeStarted)
StopDde();
else
StartDde();
}
private void Report_Click(object sender, RoutedEventArgs e)
{
// сгерерировать отчет по прошедшему тестированию
new ExcelStrategyReport(_strategy, "try.xls").Generate();
// открыть отчет
Process.Start("try.xls");
}
private void button2_Click(object sender, RoutedEventArgs e)
{
tryBuy = true;
trySell = false;
}
private void button3_Click(object sender, RoutedEventArgs e)
{
tryBuy = false;
trySell = true;
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (_trader != null)
{
//_candleManager.Stop(_series); //????????
_trader.UnRegisterMarketDepth(_strategy.Security);
_strategy.Stop();
Status.Text = "Стоп";
// останавливаем экспорт по DDE
#if EMULATOR
//ниже две сторчки для работы на эмуляторе
_trader.UnderlyingTrader.StopExport(new[] { _trader.UnderlyingTrader.SecuritiesTable, _trader.UnderlyingTrader.MyTradesTable, _trader.UnderlyingTrader.EquityPositionsTable,
_trader.UnderlyingTrader.EquityPortfoliosTable, _trader.UnderlyingTrader.OrdersTable });
#else
_trader.StopExport(new[] { _trader.SecuritiesTable, _trader.MyTradesTable, _trader.EquityPositionsTable,
_trader.EquityPortfoliosTable, _trader.OrdersTable });
#endif
if (_trader.IsConnected) _trader.Disconnect();
//_trader.Dispose();
CfgFile.WriteParam("Portfolio", Portfolios.SelectedItem.ToString());
CfgFile.WriteParam("Security", Securities1.SelectedItem.ToString());
}
base.OnClosing(e);
}
}
}
Код стратегии (выставляет ордера по нажатии кнопок в форме ) : Код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Ecng.Collections;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Indicators.Trend;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Logging;
using StockSharp.Quik;
namespace tryBot1
{
/// <summary>
/// Стратегия для проверки работы коннектора. Ручной запуск трейдов по состоянию cтатических
/// переменных базового окна tryBuy или trySell, там они меняются кнопками.
/// </summary>
public class tryStrategy : Strategy //
{
private DateTime StartTime = DateTime.Now;
private Order myOrder;
public decimal _StopLoss = 200; //strategy stop loss
public decimal _TakeProfit = 700; //strategy stop loss
public tryStrategy() { }
protected override void OnStarted()
{
Security
.WhenChanged()
.Do(TryMakeTrade).Apply(this); //когда меняется цена по инструменту проверяем "не выставить ли ордер"
//следующие события должны бы выполняться но не выполняются с чем и боремся
this.WhenNewMyTrades().Do(OnNewOrderTrades).Apply(this);
this.WhenOrderChanged().Do( ()=>
{
this.write("состояние ордера изменилось");
}).Apply(this);
//это надо для того чтобы на фьючах рабтали заявки по рынку.
this.Security.MaxPrice = 1000000;
this.Security.MinPrice = 0;
base.OnStarted();
}
/// <summary>
/// проверяем условия и пытаемся выполнить трейд
/// </summary>
/// <param name="candle"></param>
private void TryMakeTrade()
{
// если наша стратегия в процессе остановки
if (ProcessState == ProcessStates.Stopping)
{
// отменяем активные заявки
CancelActiveOrders();
return;
}
if (tryBot1.MainWindow._depth != null)
{
if ( tryBot1.MainWindow.tryBuy )
{
//отменяем все несработавшие
foreach (Strategy s in this.ChildStrategies)
{
s.CancelActiveOrders();
}
this.CancelActiveOrders();
this.write("buy Volume=" + Volume.ToString());
decimal _price = Security.BestAsk.Price + Security.MinStepSize;
myOrder = this.CreateOrder(OrderDirections.Buy, _price, Volume);
RegisterOrder(myOrder);
tryBot1.MainWindow.tryBuy = false;
}
if (tryBot1.MainWindow.trySell)
{
//отменяем все несработавшие
foreach (Strategy s in this.ChildStrategies)
{
s.CancelActiveOrders();
}
this.CancelActiveOrders();
this.write("sell Volume=" + Volume.ToString());
decimal _price = Security.BestBid.Price - Security.MinStepSize;
myOrder = this.CreateOrder(OrderDirections.Sell, _price, Volume);
RegisterOrder(myOrder);
tryBot1.MainWindow.trySell = false;
}
foreach (Strategy s in this.ChildStrategies)
{
s.Security.MaxPrice = 1000000;
s.Security.MinPrice = 0;
}
} //end if __depth
}
private void OnNewOrderTrades(IEnumerable<MyTrade> trades)
{
this.write("новый трейд");
/*
// для каждой сделки добавляем защитную пару стратегии
var protectiveStrategies = trades.Select(t =>
{
// выставляет тейк-профит в 40 пунктов
var takeProfit = new TakeProfitStrategy(t, _TakeProfit);
// выставляет стоп-лосс в 20 пунктов
var stopLoss = new StopLossStrategy(t, _StopLoss);
return new TakeProfitStopLossStrategy(takeProfit, stopLoss);
});
protectiveStrategies.ForEach( strategy => this.ChildStrategies.Add(strategy) );
*/
}
/*
override protected void OnNewMyTrades(IEnumerable<MyTrade> trades)
{
foreach(MyTrade trd in trades)
{
this.write("Trade time=" + trd.Trade.Time);
}
//aprotect.ProcessNewMyTrades(trades);
base.OnNewMyTrades(trades);
}*/
public void write(String mes)
{
LogMessage logMessage = new LogMessage(this, DateTime.Now, LogLevels.Info, mes);
RaiseLog(logMessage);
}
}
}
|
|
Спасибо:
|
|
|
|
|
kahuna
|
Дата: 22.02.2013
VassilSanych kahuna _strategy.Orders.Any(o => o == t.Order)) Не уверен, что NewMyTrades и _strategy ссылаются на одни и те же экземпляры объектов заявок в памяти. Откуда то срисовал. Поменял на _trader.Orders.Any(o => o == t.Order), но все равно результат тот же, так как само событие NewMyTrades не вызывается.
|
|
Спасибо:
|
|
|
|
|
Moadip
|
Дата: 22.02.2013
|
|
|
|
Несколько замечаний по коду. Цитата:Если оставляю #define EMULATOR сделки совершаются и событие стратегии OrderChanged срабатывает в лог попадает сообщение "состояние ордера изменилось". Если на реальном Quik (снят комментарий с #undef EMULATOR) то сделки совершаются но событие OrderChanged не срабатывает.
Как то сложно, да и лениво каждый раз комментить/раскомментить директивы препроцессора. Объявите поле _trader типа ITrader. Добавьте на форму ComboBox с двумя Item. Что нибудь типа: Код
<ComboBox Name="cmbTrader" >
<ComboBoxItem Content="Эмуляция" />
<ComboBoxItem Content="Реал" />
</ComboBox>
И потом в коде, в зависимости от того что выбранно создавать или QuikTrader или RTET<QuikTrader> Код
//Выбор шлюза
switch (cmbTrader.SelectedIndex)
{
case 0:
_trader= new RealTimeEmulationTrader<QuikTrader>(new QuikTrader(QuikTerminal.GetDefaultPath()));
break;
case 1:
_trader = new QuikTrader(QuikTerminal.GetDefaultPath())
break;
}
Рекомендую прочитать серию статей от FinDirector, почерпнете для себя много интересного. Код
_trader = new QuikTrader(QuikTerminal.GetDefaultPath()){ IsAsyncMode = true, SupportManualOrders = false };
_trader.IsAsyncMode = true;
В инициализаторе уже задано значение св-ва IsAsyncMode, нет смысла делать это еще раз. Код
Status.Text = "Сделка {0} по цене {1} по бумаге {2} по объему {3} в {4}." + System.Convert.ToString(trade.Id) + System.Convert.ToString(trade.Price) +
System.Convert.ToString(trade.Security.Code) + System.Convert.ToString(trade.Volume) + System.Convert.ToString(trade.Time);
Можно заменить на Код
Status.Text = "Сделка {Id} по цене {Price} по бумаге {Security.Code} по объему {Volume} в {Time}.".PutEx(trade)
Запуск/остановка экспорта Код
private void StartDde()
{
_trader.StartExport();
_isDdeStarted = true;
}
private void StopDde()
{
_trader.StopExport();
_isDdeStarted = false;
}
Если на экспорт запускаются все таблицы StartExport(), то нет смысла потом перечислять какие именно надо таблицы остановить. Код
//ниже две сторчки для работы на эмуляторе
_trader.UnderlyingTrader.StopExport(new[] { _trader.UnderlyingTrader.SecuritiesTable, _trader.UnderlyingTrader.MyTradesTable, _trader.UnderlyingTrader.EquityPositionsTable,
_trader.UnderlyingTrader.EquityPortfoliosTable, _trader.UnderlyingTrader.OrdersTable });
#else
_trader.StopExport(new[] { _trader.SecuritiesTable, _trader.MyTradesTable, _trader.EquityPositionsTable,
_trader.EquityPortfoliosTable, _trader.OrdersTable });
#endif
Проще вызвать StopDde() или напрямую _trader.StopExport(); Код
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (_trader != null)
{
//_candleManager.Stop(_series); //????????
_trader.UnRegisterMarketDepth(_strategy.Security);
_strategy.Stop();
Status.Text = "Стоп";
// останавливаем экспорт по DDE
#if EMULATOR
//ниже две сторчки для работы на эмуляторе
_trader.UnderlyingTrader.StopExport(new[] { _trader.UnderlyingTrader.SecuritiesTable, _trader.UnderlyingTrader.MyTradesTable, _trader.UnderlyingTrader.EquityPositionsTable,
_trader.UnderlyingTrader.EquityPortfoliosTable, _trader.UnderlyingTrader.OrdersTable });
#else
_trader.StopExport(new[] { _trader.SecuritiesTable, _trader.MyTradesTable, _trader.EquityPositionsTable,
_trader.EquityPortfoliosTable, _trader.OrdersTable });
#endif
if (_trader.IsConnected) _trader.Disconnect();
//_trader.Dispose();
CfgFile.WriteParam("Portfolio", Portfolios.SelectedItem.ToString());
CfgFile.WriteParam("Security", Securities1.SelectedItem.ToString());
}
base.OnClosing(e);
}
Дублируется base.OnClosing(e); Не смертельно, но все же. Код
//это надо для того чтобы на фьючах рабтали заявки по рынку.
this.Security.MaxPrice = 1000000;
this.Security.MinPrice = 0;
Сначала подумал что в этом причина почему не срабатывает событие NewMyTrade, т.к. не совершается сделка. По идее не должно работать. Должно прийти сообщение об ошибке, что то типа цена ордера вне диапазона. Чтобы были цены планок лучше добавить соответствующие колонки в квик таблице "Инструменты" и потом добавить их в коде. Экспорт доп. колонокПотом увидел что ценник выставляется по другому Код
_price = Security.BestBid.Price - Security.MinStepSize;
И методы BuyAtmarket и SellAtMarket не используются. Да и вы пишете что сделки совершаются. Тогда не понятно в чем может быть причина. Попробуйте максимально упростить код, чтобы проверить отрабатывает ли событие NewMyTrade. Один шлюз, минимум кода в стратегии. Попробуйте на последней сборке с codeplex, возможно причина в S#.
|
|
|
|
|
kahuna
|
Дата: 22.02.2013
|
|
|
|
Цитата: Попробуйте максимально упростить код, чтобы проверить отрабатывает ли событие NewMyTrade. Один шлюз, минимум кода в стратегии. Попробуйте на последней сборке с codeplex, возможно причина в S#.
Попробовл без изменения кода перейти на 4.1.8 , стало еще веселее, теперь Positions не показывается и в режиме эмулятора. То есть событие OrderChanged тоже не прилетает. Verifier про настройку Quik говорит - все в порядке. Упростил код. Дальше уже кажется некуда. Картина сохранилась. [confused] основной: Код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using MessageBox = System.Windows.MessageBox;
using System.Threading;
using System.Linq;
using System.Xml;
using Xceed.Wpf.Toolkit;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Xaml;
using Ecng.ComponentModel;
using StockSharp.BusinessEntities;
using StockSharp.Algo.Reporting;
using StockSharp.Quik;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Xaml;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Indicators.Trend;
using StockSharp.Logging;
using StockSharp.Algo.Testing;
namespace test
{
/// <summary>
/// Логика взаимодействия для MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private RealTimeEmulationTrader<QuikTrader> _trader;
//private QuikTrader _trader;
public static MarketDepth _depth;
private tryStrategy _strategy;
private MonitorWindow monitor;
private LogManager _logManager;
private String DefSecurity = "RIH3@RTS";
private String DefPortfolio = "SPBFUTXXXX";
public static bool tryBuy = false;
public static bool trySell = false;
public MainWindow()
{
InitializeComponent();
monitor = new MonitorWindow();
monitor.Show();
_logManager = new LogManager();
//var fileListener = new FileLogListener("{0}_{1:00}_{2:00}.txt".Put(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day));
//logManager.Listeners.Add(fileListener);
_logManager.Listeners.Add(new GuiLogListener(monitor));
}
private void Connect_Click(object sender, RoutedEventArgs e)
{
if (_trader == null || !_trader.IsConnected)
{
if (_trader == null)
{
if (QuikTerminal.GetDefaultPath().IsEmpty())
{
MessageBox.Show(this, "Путь к Quik не выбран.");
return;
}
Status.Text = "Connecting with Quck. Please wait";
_trader = new RealTimeEmulationTrader<QuikTrader>(new QuikTrader(QuikTerminal.GetDefaultPath()) { IsAsyncMode = true, SupportManualOrders = false });
// _trader = new QuikTrader(QuikTerminal.GetDefaultPath()){ IsAsyncMode = true, SupportManualOrders = false };
_trader.Connected += () =>
{
// подписываемся на событие появление инструментов
_trader.NewSecurities += securities => this.GuiAsync(() =>
{
Securities1.ItemsSource = _trader.Securities;
int i = 0;
foreach (Object item in Securities1.Items)
{
Securities1.SelectedIndex = i;
if (item.ToString().Equals(DefSecurity))
{
break;
}
i++;
}
// если инструмент и стакан уже появились
if (Securities1.SelectedItem != null)
{
Status.Text = "Инструмент появился.";
}
});
_trader.NewPortfolios += portfolios => this.GuiAsync(() =>
{
Portfolios.ItemsSource = _trader.Portfolios;
int i = 0;
foreach (Object item in Portfolios.Items)
{
Portfolios.SelectedIndex = i;
if (item.ToString().Equals(DefPortfolio))
{
break;
}
i++;
}
});
// подписываемся на событие появления моих новых сделок
_trader.NewMyTrades += myTrades => this.GuiAsync(() =>
{
if (_strategy != null)
{
// найти те сделки, которые совершила стратегия
//myTrades = myTrades.Where(t => _strategy.Orders.Any(o => o == t.Order));
myTrades = myTrades.Where(t => _trader.Orders.Any(o => o == t.Order));
}
foreach (var myTrade in myTrades)
{
var trade = myTrade.Trade;
Status.Text = "Сделка {Id} по цене {Price} по бумаге {Security.Code} по объему {Volume} в {Time}.".PutEx(trade);
}
});
// подписываемся на событие обновления стакана
_trader.MarketDepthsChanged += depths => this.GuiAsync(() =>
{
if (_depth == null && DefSecurity != null)
{
_depth = depths.FirstOrDefault(d => d.Security.Equals( (Security) this.Securities1.SelectedItem ));
while (_depth == null) ;
Status.Text = "Стакан появился.";
}
});
};//КОНЕЦ _trader.Conected
_trader.ConnectionError += ex =>
{
if (ex != null)
this.GuiAsync(() => MessageBox.Show(this, ex.ToString()));
};
this.GuiAsync(() =>
{
Connect.IsEnabled = false;
Report.IsEnabled = true;
});
// подписываемся на событие о неудачной регистрации заявок
this._trader.OrdersRegisterFailed += OrdersFailed;
// подписываемся на событие о неудачном снятии заявок
this._trader.OrdersCancelFailed += OrdersFailed;
// подписываемся на событие о неудачной регистрации стоп-заявок
this._trader.StopOrdersRegisterFailed += OrdersFailed;
// подписываемся на событие о неудачном снятии стоп-заявок
this._trader.StopOrdersCancelFailed += OrdersFailed;
// запускаем экспорт по DDE
_trader.Connect();
while (!_trader.IsConnected) { }
Status.Text = "Connected with Quik terminal";
StartDde();
#if EMULATOR
_trader.UnderlyingTrader.LogLevel = LogLevels.Debug;
_logManager.Sources.Add(_trader.UnderlyingTrader);
#else
_trader.LogLevel = LogLevels.Debug;
_logManager.Sources.Add(_trader);
#endif
}
else
_trader.Disconnect();
}
}
private void OrdersFailed(IEnumerable<OrderFail> fails)
{
this.GuiAsync(() =>
{
foreach (var fail in fails)
MessageBox.Show(this, fail.Error.ToString(), "Ошибка регистрации заявки");
});
}
private void StartDde()
{
_trader.StartExport();
}
private void StopDde()
{
_trader.StopExport();
}
private void OnStrategyPropertyChanged(object sender, PropertyChangedEventArgs e)
{
_trader.AddInfoLog("OnStrategyPropertyChanged");
this.GuiAsync(() =>
{
//Status.Content = _strategy.ProcessState;
Status.Text = _strategy.ProcessState.ToString();
PnL.Content = _strategy.PnLManager.PnL;
Slippage.Content = _strategy.SlippageManager.Slippage;
Position.Content = _strategy.PositionManager.Position;
Latency.Content = _strategy.Latency;
});
}
private void SwitchOn_Click(object sender, RoutedEventArgs e)
{
if (_strategy == null )
{
// создаем торговую стратегию,
_strategy = new tryStrategy()
{
Volume = 1,
Security = (Security)this.Securities1.SelectedItem,
Portfolio = (Portfolio)this.Portfolios.SelectedItem,
Trader = _trader
};
_strategy.PropertyChanged += OnStrategyPropertyChanged;
_logManager.Sources.Add(_strategy);
if (_strategy.ProcessState == ProcessStates.Stopped)
{
// запускаем процесс получения стакана, необходимый для работы алгоритма котирования
_trader.RegisterMarketDepth((Security)this.Securities1.SelectedItem);
_strategy.Start();
Status.Text = "Старт";
}
else
{
_trader.UnRegisterMarketDepth((Security)this.Securities1.SelectedItem);
_strategy.Stop();
Status.Text = "Стоп";
}
}
}
private void Report_Click(object sender, RoutedEventArgs e)
{
// сгерерировать отчет по прошедшему тестированию
new ExcelStrategyReport(_strategy, "try.xls").Generate();
// открыть отчет
Process.Start("try.xls");
}
private void button2_Click(object sender, RoutedEventArgs e)
{
tryBuy = true;
trySell = false;
}
private void button3_Click(object sender, RoutedEventArgs e)
{
tryBuy = false;
trySell = true;
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (_trader != null)
{
_trader.UnRegisterMarketDepth(_strategy.Security);
_strategy.Stop();
Status.Text = "Стоп";
// останавливаем экспорт по DDE
StopDde();
if (_trader.IsConnected) _trader.Disconnect();
//_trader.Dispose();
}
base.OnClosing(e);
}
}
}
для стратегии: Код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Ecng.Collections;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Indicators.Trend;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Logging;
using StockSharp.Quik;
namespace test
{
/// <summary>
/// Стратегия для проверки работы коннектора. Ручной запуск трейдов по состоянию cтатических
/// переменных базового окна tryBuy или trySell, там они меняются кнопками.
/// </summary>
public class tryStrategy : Strategy //
{
private Order myOrder;
public tryStrategy() { }
protected override void OnStarted()
{
Security
.WhenChanged()
.Do(TryMakeTrade).Apply(this); //когда меняется цена по инструменту проверяем "не выставить ли ордер"
//следующие события должны бы выполняться но не выполняются с чем и боремся
this.WhenNewMyTrades().Do(OnNewOrderTrades).Apply(this);
this.WhenOrderChanged().Do( ()=>
{
this.write("состояние ордера изменилось");
}).Apply(this);
this.WhenError().Do(() =>
{
this.write("прилетела ошибка");
}).Apply(this);
this.WhenOrderRegistered().Do(() =>
{
this.write("зарегистрирован ордер");
}).Apply(this);
this.WhenPnLChanged().Do(() =>
{
this.write("профит.лосс сменился");
}).Apply(this);
this.WhenWarning().Do(() =>
{
this.write("желтая карточка");
}).Apply(this);
base.OnStarted();
}
/// <summary>
/// проверяем условия и пытаемся выполнить трейд
/// </summary>
/// <param name="candle"></param>
private void TryMakeTrade()
{
// если наша стратегия в процессе остановки
if (ProcessState == ProcessStates.Stopping)
{
// отменяем активные заявки
CancelActiveOrders();
return;
}
if (test.MainWindow._depth != null) //стакан работает?
{
if ( test.MainWindow.tryBuy )
{
this.write("buy Volume=" + Volume.ToString());
decimal _price = Security.BestAsk.Price + Security.MinStepSize;
myOrder = this.CreateOrder(OrderDirections.Buy, _price, Volume);
RegisterOrder(myOrder);
test.MainWindow.tryBuy = false;
}
if (test.MainWindow.trySell)
{
this.write("sell Volume=" + Volume.ToString());
decimal _price = Security.BestBid.Price - Security.MinStepSize;
myOrder = this.CreateOrder(OrderDirections.Sell, _price, Volume);
RegisterOrder(myOrder);
test.MainWindow.trySell = false;
}
} //end if __depth
}
private void OnNewOrderTrades(IEnumerable<MyTrade> trades)
{
this.write("новый трейд");
}
public void write(String mes)
{
LogMessage logMessage = new LogMessage(this, DateTime.Now, LogLevels.Info, mes);
RaiseLog(logMessage);
}
}
}
|
|
Спасибо:
|
|
|
|
|
VassilSanych
|
Дата: 23.02.2013
kahuna И следующий код никогда не исполняется (то что внутри цикла foreach) хотя ордера выставляются.
Попробуйте всё-таки вставить строчку логирования перед foreach. Возможно всё-таки косяк с фильтром. Говоря о заявке в памяти, я подразумевал, что, может быть, лучше проверять какие-нибудь скалярные свойства ордеров, а не ссылки на объекты.
|
|
Спасибо:
|
|
|
|
|
kahuna
|
Дата: 25.02.2013
VassilSanych kahuna И следующий код никогда не исполняется (то что внутри цикла foreach) хотя ордера выставляются.
Попробуйте всё-таки вставить строчку логирования перед foreach. Возможно всё-таки косяк с фильтром. Говоря о заявке в памяти, я подразумевал, что, может быть, лучше проверять какие-нибудь скалярные свойства ордеров, а не ссылки на объекты. Попробовал поставил, выполнение до цикла просто не доходит. Не вызывается совсем этот обработчик события NewMyTrades.
|
|
Спасибо:
|
|
|
|