Kazai Mazai
|
Дата: 21.10.2013
|
|
|
|
Часть 2. Почва для удобного добавления стратегий. В прошлый раз я немного поторопился с обновлением версии S#. Нашлись кое-какие неполадки в коннекторе и пришлось откатиться. Тем не менее, там все актуально за исключением парочки нюансов при создании новых подключений. Главное делать по аналогии, и все будет хорошо[thumbup] Добавил базовые свойства стратегии. Код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using StockSharp.BusinessEntities;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
namespace Robot
{
public class BaseStrategyProperties:INotifyPropertyChanged
{
private string _name = "Новая стратегия";
private string _security = "TEST@TEST";
private string _portfolio = "TEST_PORTFOLIO";
private decimal _volume = 1;
private Dictionary<long, Order> _ordersByTransactionId = new Dictionary<long, Order>();
private Dictionary<long, Security> _securitiesByTransactionId = new Dictionary<long, Security>();
private Dictionary<long, Portfolio> _portfoliosByTransactionId = new Dictionary<long, Portfolio>();
private Dictionary<long, IEnumerable<Trade>> _tradesByTransactionId = new Dictionary<long, IEnumerable<Trade>>();
private Dictionary<long, Exchange> _exchangesByTransactionId = new Dictionary<long, Exchange>();
private bool _schedulerIsEnabled;
private List<TimeRangeProperties> _schedule = new List<TimeRangeProperties>(10);
[DisplayName(@"Название")]
[Description(@"Название стратегии")]
[Category(@"Основные")]
//[CategoryOrder(0)]
[PropertyOrder(0)]
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("Name");
}
}
[DisplayName(@"Инструмент")]
[Description(@"Код торгового инструмента")]
[Category(@"Основные")]
//[CategoryOrder(0)]
[PropertyOrder(1)]
[Editor(typeof(SecurityIdEditor), typeof(SecurityIdEditor))]
public string Security
{
get { return _security; }
set
{
_security = value;
OnPropertyChanged("Security");
}
}
[DisplayName(@"Портфель")]
[Description(@"Имя портфеля")]
[Category(@"Основные")]
//[CategoryOrder(0)]
[PropertyOrder(3)]
[Editor(typeof(PortfolioNameEditor), typeof(PortfolioNameEditor))]
public string Portfolio
{
get { return _portfolio; }
set
{
_portfolio = value;
OnPropertyChanged("Portfolio");
}
}
[DisplayName(@"Объем")]
[Description(@"Объем для открытия позиций")]
[Category(@"Основные")]
//[CategoryOrder(0)]
[PropertyOrder(4)]
public decimal Volume
{
get { return _volume; }
set
{
if (value < 0)
{
return;
}
_volume = value;
OnPropertyChanged("Volume");
}
}
[Category(@"Планировщик")]
//[CategoryOrder(5)]
[DisplayName(@"Включен")]
[Description(@"Включен ли запуск по расписанию для данной стратегии.")]
[PropertyOrder(0)]
public bool SchedulerIsEnabled
{
get { return _schedulerIsEnabled; }
set
{
_schedulerIsEnabled = value;
OnPropertyChanged("SchedulerIsEnabled");
}
}
[Category(@"Планировщик")]
//[CategoryOrder(5)]
[DisplayName(@"Время работы")]
[Description(@"Настройка времени автоматической работы стратегии.")]
[PropertyOrder(1)]
[Editor(typeof(ScheduleEditor), typeof(ScheduleEditor))]
public List<TimeRangeProperties> Schedule
{
get { return _schedule; }
set
{
_schedule = value;
OnPropertyChanged("Schedule");
}
}
[DisplayName(@"ОрдерПоАйдиТранзакции")]
[Description(@"ОрдерПоАйдиТранзакции")]
[Category(@"Для работы")]
[PropertyOrder(0)]
public Dictionary<long, Order> OrdersByTransactionId
{
get { return _ordersByTransactionId; }
set
{
_ordersByTransactionId = value;
OnPropertyChanged("OrdersByTransactionId");
}
}
[DisplayName(@"ИнструментПоАйдиТранзакции")]
[Description(@"ИнструментПоАйдиТранзакции")]
[Category(@"Для работы")]
[PropertyOrder(0)]
public Dictionary<long, Security> SecuritiesByTransactionId
{
get { return _securitiesByTransactionId; }
set
{
_securitiesByTransactionId = value;
OnPropertyChanged("SecuritiesByTransactionId");
}
}
[DisplayName(@"СделкиПоАйдиТранзакции")]
[Description(@"СделкиПоАйдиТранзакции")]
[Category(@"Для работы")]
[PropertyOrder(0)]
public Dictionary<long, IEnumerable<Trade>> TradesByTransactionId
{
get { return _tradesByTransactionId; }
set
{
_tradesByTransactionId = value;
OnPropertyChanged("TradesByTransactionId");
}
}
[DisplayName(@"ПортфелиПоАйдиТранзакции")]
[Description(@"ПортфелиПоАйдиТранзакции")]
[Category(@"Для работы")]
[PropertyOrder(0)]
public Dictionary<long, Portfolio> PortfoliosByTransactionId
{
get { return _portfoliosByTransactionId; }
set
{
_portfoliosByTransactionId = value;
OnPropertyChanged("PortfoliosByTransactionId");
}
}
[DisplayName(@"БиржиПоАйдиТранзакции")]
[Description(@"БиржиПоАйдиТранзакции")]
[Category(@"Для работы")]
[PropertyOrder(0)]
public Dictionary<long, Exchange> ExchangesByTransactionId
{
get { return _exchangesByTransactionId; }
set
{
_exchangesByTransactionId = value;
OnPropertyChanged("ExchangesByTransactionId");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
и базовую стратегию, восстанавливающую ордера,сделки и позиции при перезапуске. Код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StockSharp.Algo;
using StockSharp.BusinessEntities;
namespace Robot.Base
{
public class BaseSavingStatesStrategy: BaseStrategy
{
public BaseStrategyProperties Params { set; get; }
private bool _isFirstStart;
public BaseSavingStatesStrategy()
{
_isFirstStart = true;
}
protected void SaveStateToParams()
{
foreach (var order in Orders)
{
var transactionId = order.TransactionId;
if (Params.OrdersByTransactionId.ContainsKey(transactionId))
{
Params.OrdersByTransactionId[transactionId] = order;
}
else
{
Params.OrdersByTransactionId.Add(transactionId, order);
}
var myTrades = order.GetTrades();
List<Trade> trades = new List<Trade>();
foreach (var myTrade in myTrades)
{
trades.Add(myTrade.Trade);
}
if (Params.TradesByTransactionId.ContainsKey(transactionId))
{
Params.TradesByTransactionId[transactionId] = trades;
}
else
{
Params.TradesByTransactionId.Add(transactionId, trades);
}
if (Params.SecuritiesByTransactionId.ContainsKey(transactionId))
{
Params.SecuritiesByTransactionId[transactionId] = order.Security;
}
else
{
Params.SecuritiesByTransactionId.Add(transactionId, order.Security);
}
if (Params.ExchangesByTransactionId.ContainsKey(transactionId))
{
Params.ExchangesByTransactionId[transactionId] = order.Security.ExchangeBoard.Exchange;
}
else
{
Params.ExchangesByTransactionId.Add(transactionId, order.Security.ExchangeBoard.Exchange);
}
if (Params.PortfoliosByTransactionId.ContainsKey(transactionId))
{
Params.PortfoliosByTransactionId[transactionId] = order.Portfolio;
}
else
{
Params.PortfoliosByTransactionId.Add(transactionId, order.Portfolio);
}
}
}
protected void LoadStateFromParams()
{
foreach (var transactionId in Params.OrdersByTransactionId.Keys)
{
var order = Params.OrdersByTransactionId[transactionId];
if (order != null)
{
order.Trader = Trader;
var security = Params.SecuritiesByTransactionId[transactionId];
if (security != null)
{
var exchange = Params.ExchangesByTransactionId[transactionId];
if (exchange != null) security.ExchangeBoard.Exchange = exchange;
security.Trader = Trader;
order.Security = security;
}
var portfolio = Params.PortfoliosByTransactionId[transactionId];
if (portfolio != null)
{
Portfolio.Trader = Trader;
order.Portfolio = portfolio;
}
var myTrades = new List<MyTrade>();
var trades = Params.TradesByTransactionId[transactionId];
if (trades != null)
foreach (var trade in trades)
{
var myTrade = new MyTrade();
myTrade.Order = order;
myTrade.Trade = trade;
myTrades.Add(myTrade);
}
if (myTrades.Count > 0)
{
AttachOrder(order, myTrades);
}
}
}
}
protected override void OnStarted()
{
base.OnStarted();
if(_isFirstStart)
{
_isFirstStart = false;
LoadStateFromParams();
}
}
protected override void OnStopped()
{
SaveStateToParams();
base.OnStopped();
}
}
}
Правильней было бы сохранять все в бд, используя EntityRegistry, но как-то с базой гидры не хотело взлетать. А так работает, ну и окей. Не так уж часто стратегии перезапускаются в самом деле. Немного поменял добавление стратегий. Теперь, когда нужно будет включить новую стратегию, можно просто сделать для нее команду добавления, приписать в xml и она появится в менюшке добавления. Главное - все по аналогии.[thumbup]
|
|
|
|
|
Kazai Mazai
|
Дата: 25.10.2013
|
|
|
|
Часть 3.1. Добавление своих стратегий. Эта история полна нюансов. В шелле хорошо показано, на примере одной стратегии как все работает и т.д. Добавить свою взамен существующей тоже легко - меняем да и все. Либо по-варварски вставляем в существующую новые внутренности. Но тут не так все гибко, чтобы наряду с существующими в два щелчка добавить новые стратегии и чтобы все прекрасно работало и сохранялось. Можно чуть менее чем полностью переделать SettingsEngine, половину кода связанного с добавлением стратегий, и только потом добавлять какие угодно новые стратегии в два щелчка. А можно сделать минимум изменений, прикрутив маленькие костыли и затем добавлять новые стратегии не в 2 а в 6 щелчков, о чем и пойдет речь дальше. Я уже подготовил небольшую почву, наподобие той, про которую было во 2-ой части. Когда мне удастся подружиться с ТФС, эти изменения уже будут в шелле. Может показаться, что кода много, но на самом деле там 90% копи паст. Добавляем заготовку для стратегии, для параметров и параметров тестирования, которые когда-нибудь наполним содержанием. Код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Robot.Strategies
{
public class HustleEveryDayStrategyProperties :BaseShellStrategyProperties
{
}
public class HustleEveryDayStrategyTestingProperties:BaseShellTestingProperties
{
}
public class HustleEveryDayStrategy:BaseShellStrategy
{
}
}
Идем в SettingsEngine, добавляем методы для сохранения и загрузки параметров для нового типа стратегий. Код
private const string HustleEveryDayStrategies = @"HustleEveryDayStrategies.xml";
private const string TestingHustleEveryDayStrategies = @"TestingHustleEveryDayStrategies.xml";
public void SaveHustleEveryDayStrategiesProperties(List<HustleEveryDayStrategyProperties> properties)
{
this.AddInfoLog("Сохранение стратегий в {0}", HustleEveryDayStrategies);
using (var writer = new StreamWriter(HustleEveryDayStrategies, false))
{
var mySerializer = new XmlSerializer(typeof(List<HustleEveryDayStrategyProperties>));
mySerializer.Serialize(writer, properties);
}
}
public List<HustleEveryDayStrategyProperties> LoadHustleEveryDayStrategiesProperties()
{
this.AddInfoLog("Загрузка стратегий из {0}", HustleEveryDayStrategies);
var result = new List<HustleEveryDayStrategyProperties>();
if (File.Exists(HustleEveryDayStrategies))
{
try
{
using (var reader = new StreamReader(HustleEveryDayStrategies))
{
var x = new XmlSerializer(typeof(List<HustleEveryDayStrategyProperties>));
result = (List<HustleEveryDayStrategyProperties>)x.Deserialize(reader);
}
}
catch (Exception ex)
{
this.AddErrorLog("Ошибка загрузки {0}: {1}", HustleEveryDayStrategies, ex.Message);
}
}
return result;
}
public void SaveTestingHustleEveryDayStrategyProperties(List<HustleEveryDayStrategyTestingProperties> properties)
{
this.AddInfoLog("Сохранение тестовых стратегий в {0}", TestingHustleEveryDayStrategies);
using (var writer = new StreamWriter(TestingHustleEveryDayStrategies, false))
{
var mySerializer = new XmlSerializer(typeof(List<HustleEveryDayStrategyTestingProperties>));
mySerializer.Serialize(writer, properties);
}
}
public List<HustleEveryDayStrategyTestingProperties> LoadTestingHustleEveryDayStrategyProperties()
{
this.AddInfoLog("Загрузка стратегий тестирования из {0}", TestingHustleEveryDayStrategies);
var result = new List<HustleEveryDayStrategyTestingProperties>();
if (File.Exists(TestingStrategiesXml))
{
using (var reader = new StreamReader(TestingHustleEveryDayStrategies))
{
var x = new XmlSerializer(typeof(List<HustleEveryDayStrategyTestingProperties>));
result = (List<HustleEveryDayStrategyTestingProperties>)x.Deserialize(reader);
}
}
return result;
}
Идем в Main. Добавляем маленький костыль. Код
private List<HustleEveryDayStrategy> _hustleEveryDayStrategies = new List<HustleEveryDayStrategy>();
private List<HustleEveryDayStrategy> _hustleEveryDayTestingStrategies = new List<HustleEveryDayStrategy>();
И почти как под копирку методы для добавления стратегий: Код
private void AddHustleEveryDayStrategy()
{
var properties = new HustleEveryDayStrategyProperties
{
// TODO: check if the stategy with same does exist
Name = "Новая стратегия {0}".Put(_newStrategyCount++),
};
AddHustleEveryDayStrategy(properties);
SaveStrategies();
}
private void AddHustleEveryDayStrategy(HustleEveryDayStrategyProperties properties)
{
var strategy = new HustleEveryDayStrategy
{
Params = properties,
Trader = ConnectionEngine.Instance.Trader
};
_logManager.Sources.Add(strategy);
var doc = new LayoutDocument
{
Title = strategy.Params.Name,
Content = new StrategyDocument
{
Strategy = strategy
},
CanClose = false
};
strategy.Params.PropertyChanged += (s, a) =>
{
if (a.PropertyName == "Name")
{
doc.Title = strategy.Params.Name;
}
SaveStrategies();
};
_documents.Add(strategy, doc);
_hustleEveryDayStrategies.Add(strategy);
this.AddInfoLog("Добавлена стратегия '{0}'", strategy.Name);
StrategiesDocumentPane.Children.Add(doc);
}
private void AddHustleEverydayTestingStrategy()
{
var properties = new HustleEveryDayStrategyTestingProperties
{
Name = "Тестирование {0}".Put(_newTestingCount++)
};
AddTestingStrategy(properties);
SaveTestingStrategies();
}
private void AddHustleEverydayTestingStrategy(HustleEveryDayStrategyTestingProperties properties)
{
var strategy = new HustleEveryDayStrategy
{
Params = properties,
Trader = ConnectionEngine.Instance.Trader
};
var doc = new LayoutDocument()
{
Title = strategy.Params.Name,
Content = new TestingDocument
{
Strategy = strategy
},
CanClose = false
};
strategy.Params.PropertyChanged += (s, a) =>
{
if (a.PropertyName == "Name")
{
doc.Title = strategy.Params.Name;
}
SaveTestingStrategies();
};
_testingDocuments.Add(strategy, doc);
_hustleEveryDayTestingStrategies.Add(strategy);
this.AddInfoLog("Добавлена тестовая стратегия '{0}'", strategy.Name);
StrategiesDocumentPane.Children.Add(doc);
}
Нужно добавить в InitializeConfiguration() - методе восстановления из настроек. Код
var hustleProperties = SettingsEngine.Instance.LoadHustleEveryDayStrategiesProperties();
foreach (var property in hustleProperties)
{
AddHustleEveryDayStrategy(property);
}
var testingHustleProperties = SettingsEngine.Instance.LoadTestingHustleEveryDayStrategyProperties();
foreach (var properties in testingHustleProperties)
{
AddTestingStrategy(properties);
}
Ну вот. Теперь сохранение настроек стратегий будет работать не правильно, а удаление будет удалять только из интерфейса, а при перезапуске все будет по-прежнему. И это только на первый взгляд. Как починить это, а также о том, как добавить кнопки добавления стратегии в интерфейс, узнаем в следующей подчасти части 3.
|
|
|
|
|
Bond
|
Дата: 25.10.2013
Прям триллер какой-то! Ждем продолжения! [thumbup]
|
|
Спасибо:
|
|
|
|
|
Kazai Mazai
|
Дата: 05.11.2013
|
|
|
|
Переделать метод сохранения, который в MainWindow.xaml.cs можно как-нибудь в таком духе: Код
private void SaveStrategies()
{
SettingsEngine.Instance.SaveHustleEveryDayStrategiesProperties(
_hustleEveryDayStrategies.Select(s => (HustleEveryDayStrategyProperties)s.Params).ToList());
var otherStrategies = _documents.Keys.Where( s=>! _hustleEveryDayStrategies.Any(str=> str.Params.Name==s.Params.Name)).Select(strategy => strategy.Params).ToList();
SettingsEngine.Instance.SaveStrategies(otherStrategies);
}
Сохранять сначала наши новые кастомные стратегии, а потом фильтровать все, например по имени. Но по идее, если уж пилить стратегии, то для каждого вашего типа стратегий будет свой массив, который и следует сохранять по отдельности, и ничего уже потом не фильтровать. Аналогично с сохранением свойств тестовых стратегий: Код
private void SaveTestingStrategies()
{
SettingsEngine.Instance.SaveTestingHustleEveryDayStrategyProperties(
_hustleEveryDayTestingStrategies.Select(s => (HustleEveryDayStrategyTestingProperties)s.Params).ToList());
var strategies = _testingDocuments.Keys.Where( s=>! _hustleEveryDayTestingStrategies.Any(str=> str.Params.Name==s.Params.Name)).Select(strategy => (BaseShellTestingProperties)strategy.Params).ToList();
SettingsEngine.Instance.SaveTestingStrategies(strategies);
}
В методе Код
private void ExecutedRemoveStrategy(object sender, ExecutedRoutedEventArgs e)
Там где у нас обработка нажатого "да" Код
if (result == MessageBoxResult.Yes)
{
this.AddInfoLog("Удаление стратегии '{0}'", strategy.Params.Name);
var doc = _documents[strategy];
_documents.Remove(strategy);
StrategiesDocumentPane.RemoveChild(doc);
_hustleEveryDayStrategies.RemoveAll(s => s.Params.Name == strategy.Params.Name);
SaveStrategies();
}
Удаляем еще и из нашего списка стратегий с фильтрацией по имени. Лучше, конечно, что б у всех стратегий был какой-то id, и все сравнения проводить по нему. Что бы можно было было из интерфейса добавить свежих стратегий: Добавляем команду там же в MainWindow.xaml.cs, Код
public static RoutedCommand AddHustleStrategyCommand = new RoutedCommand();
далее методы для команды. Код
private void ExecutedAddHustleStrategy(object sender, ExecutedRoutedEventArgs e)
{
AddHustleEveryDayStrategy();
AllStrategies.ListViewStrategies.ItemsSource = _documents.Keys.ToList();
}
private void CanExecuteAddHuslteStrategy(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
e.Handled = true;
}
Нужно теперь подключить команду к gui. В MainWindow.xaml: Там есть такая штука, комманд биндинг. Добавляем вот что: Код
<CommandBinding Command="{x:Static Robot:MainWindow.AddHustleStrategyCommand}"
Executed="ExecutedAddHustleStrategy"
CanExecute="CanExecuteAddHustleStrategy" />
далее в нем же ищем "AddStrategyCommand"? находим его в контексте меню итемс, и аналогично добавляем Код
<MenuItem Header="Добавить хассол" Command="{x:Static Robot:MainWindow.AddHustleStrategyCommand}"/>
Ну вот, теперь все готово.
|
|
|
|
|
Kazai Mazai
|
Дата: 05.11.2013
|
|
|
|
Небольшое лирическое отступление...
Там выше в стратегии реализовывались методы для сохранения ордеров, позиций и т.д.
У меня так раньше было реализовано, не на s# shell, но все же. Возможно версия s# была другая, возможно я где-то наошибался, но недавно на s# shell уже обнаружил, что такой способ не работает. Т.е. если положить Dictionary с ордерами (то что в базовых Properties) в SettingsStorage и попытаться сериализовать, ничего не получится. Если положить SettingsStorage с ордерами в SettingsStorage, тоже не заработало, хотя раньше все прокатывало, если мне не изменяет память.
Во-вторых это, на мой взгляд, не совсем корректно, если в стратегию ордера и сделки поступают не только из Trader, но еще и напрямую из хранилища.
Может возникнуть какая-нибудь дурацкая ситуация, если после перезапуска один и тот же ордер прийдет в стратегию и шлюза и из хранилища, и бог его знает как-там оно все разбираться внутри будет.
Поэтому, в Properties стратегии лучше хранить просто список orderIDs, брать их от Trader'a и привязывать.
Если торговый терминал не передает историю ордеров, прийдется "усовершенствовать" Trader и реализовать возможность сохранения в бд.
Вот такие вот рекомендации.[smile]
|
|
Спасибо:
|
|
|
|
|
dij1
|
Дата: 06.11.2013
Вопрос немного не в тему. Удалось ли Вам поймать устойчивую конфигурацию работы с Plaza 2, т.е. версию, которая с плазой пашет?
|
|
Спасибо:
|
|
|
|
|
Kazai Mazai
|
Дата: 07.11.2013
dij1 Вопрос немного не в тему. Удалось ли Вам поймать устойчивую конфигурацию работы с Plaza 2, т.е. версию, которая с плазой пашет? Я плазой вообще дел не имел
|
|
Спасибо:
|
|
|
|
|
Kazai Mazai
|
Дата: 19.11.2013
|
|
|
|
По просьбам телезрителей(как минимум одного) сделал зарисовочку для сопровождения позиции. Открывается прямо при старте, и выходит в какое-то время, а также по стопам и нескольким ценовым тейкам, передвигая стоп в б\у. Есть кое-какие лишние проверки, потому что кусочки взяты из стратегии на нескольких инструментах, но хуже не будет. Код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Logging;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
namespace Robot.Strategies
{
public class HustleEveryDayStrategyProperties :BaseShellStrategyProperties
{
private decimal _takeProfit1 = 10000000;
[DisplayName(@"1-й тейк профит")]
[Description(@"Цена для 1-й цели")]
[Category(@"Параметры")]
[PropertyOrder(0)]
public decimal TakeProfit1
{
get { return _takeProfit1; }
set
{
_takeProfit1 = value;
OnPropertyChanged("TakeProfit1");
}
}
private decimal _takeProfit2 = 10000000;
[DisplayName(@"2-й тейк профит")]
[Description(@"Цена для 2-й цели")]
[Category(@"Параметры")]
[PropertyOrder(0)]
public decimal TakeProfit2
{
get { return _takeProfit2; }
set
{
_takeProfit2 = value;
OnPropertyChanged("TakeProfit2");
}
}
private decimal _takeProfit3 = 10000000;
[DisplayName(@"3-й тейк профит")]
[Description(@"Цена для 3-й цели")]
[Category(@"Параметры")]
[PropertyOrder(0)]
public decimal TakeProfit3
{
get { return _takeProfit3; }
set
{
_takeProfit3 = value;
OnPropertyChanged("TakeProfit3");
}
}
private decimal _stoploss = 10000000;
[DisplayName(@"стоп лосс")]
[Description(@"Цена для стоп лосса")]
[Category(@"Параметры")]
[PropertyOrder(0)]
public decimal Stoploss
{
get { return _stoploss; }
set
{
_stoploss = value;
OnPropertyChanged("Stoploss");
}
}
private DateTime _closeTime = new DateTime(2000,1,1,1,1,1);
[DisplayName(@"Время закрытия")]
[Description(@"Время закрытия сделки")]
[Category(@"Параметры")]
[PropertyOrder(0)]
public DateTime CloseTime
{
get { return _closeTime; }
set
{
_closeTime = value;
OnPropertyChanged("CloseTime");
}
}
private OrderDirections _orderDirection = OrderDirections.Buy;
[DisplayName(@"Направление сделки")]
[Description(@"Направление сделки")]
[Category(@"Параметры")]
[PropertyOrder(0)]
public OrderDirections OrderDirection
{
get { return _orderDirection; }
set
{
_orderDirection = value;
OnPropertyChanged("OrderDirection");
}
}
}
public class HustleEveryDayStrategyTestingProperties:BaseShellTestingProperties
{
}
public class HustleEveryDayStrategy:BaseShellStrategy
{
protected override void OnStarted()
{
base.OnStarted();
var currentTime = Trader.GetMarketTime(Security.ExchangeBoard.Exchange);
this.AddInfoLog("Текущее рыночное время: {0}.".Put(currentTime));
var currentClosePositionsTime = ((HustleEveryDayStrategyProperties) Params).CloseTime;
this.AddInfoLog("Текущее время проверки выхода по тайм-стопу: {0}.".Put(currentClosePositionsTime));
if (currentTime > currentClosePositionsTime)
{
var newClosePositionsTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day,
currentClosePositionsTime.Hour, currentClosePositionsTime.Minute,
currentClosePositionsTime.Second);
this.AddInfoLog("Новое время проверки выхода по тайм-стопу: {0}.".Put(newClosePositionsTime));
((HustleEveryDayStrategyProperties) Params).CloseTime = newClosePositionsTime;
}
Security
.WhenTimeCome(((HustleEveryDayStrategyProperties)Params).CloseTime)
.Do(CheckForExitByTimeTargets)
.Apply(this);
Security
.WhenChanged()
.Do(CheckForExitByPriceTargets)
.Apply(this);
SubscriptionEngine.Instance.RegisterSecurity(this, Security);
if(((HustleEveryDayStrategyProperties)Params).OrderDirection==OrderDirections.Buy)
{
PlaceBuyMarketOrder(Security,Volume);
}
else
{
PlaceSellMarketOrder(Security, Volume);
}
}
private void CheckForExitByPriceTargets()
{
this.AddInfoLog("Проверка выхода по целям.");
if( PositionManager.Positions.Any(p=> p.Security.Code==Security.Code))
{
var position = PositionManager.Positions.First(p => p.Security.Code == Security.Code);
if (position.CurrentValue > 0)
{
if (Security.LastTrade.Price <= ((HustleEveryDayStrategyProperties)Params).Stoploss)
{
PlaceSellMarketOrder(position.Security, position.CurrentValue);
return;
}
if (Security.LastTrade.Price >= ((HustleEveryDayStrategyProperties)Params).TakeProfit3)
{
PlaceSellMarketOrder(position.Security, position.CurrentValue);
return;
}
if (Security.LastTrade.Price >= ((HustleEveryDayStrategyProperties)Params).TakeProfit2)
{
PlaceSellMarketOrder(position.Security,decimal.Floor(0.5m*position.CurrentValue));
((HustleEveryDayStrategyProperties)Params).Stoploss =
((HustleEveryDayStrategyProperties)Params).TakeProfit1;
return;
}
if (Security.LastTrade.Price >= ((HustleEveryDayStrategyProperties)Params).TakeProfit1)
{
PlaceSellMarketOrder(position.Security, decimal.Floor(0.33m * position.CurrentValue));
if(MyTrades.Any(t=>t.Trade.Security.Code==Security.Code))
{
var myTradesOrderedByDate = MyTrades.ToList().OrderBy(t => t.Trade.Time);
var trade = myTradesOrderedByDate.Last(t => t.Trade.Security.Code == Security.Code);
var entryPrice = trade.Trade.Price;
((HustleEveryDayStrategyProperties) Params).Stoploss = entryPrice;
}
return;
}
}
else
{
if (position.CurrentValue < 0)
{
if (Security.LastTrade.Price >= ((HustleEveryDayStrategyProperties)Params).Stoploss)
{
PlaceBuyMarketOrder(position.Security, position.CurrentValue);
return;
}
if (Security.LastTrade.Price <= ((HustleEveryDayStrategyProperties)Params).TakeProfit3)
{
PlaceBuyMarketOrder(position.Security, position.CurrentValue);
return;
}
if (Security.LastTrade.Price <= ((HustleEveryDayStrategyProperties)Params).TakeProfit2)
{
PlaceBuyMarketOrder(position.Security, decimal.Floor(0.5m * position.CurrentValue));
((HustleEveryDayStrategyProperties)Params).Stoploss =
((HustleEveryDayStrategyProperties)Params).TakeProfit1;
return;
}
if (Security.LastTrade.Price <= ((HustleEveryDayStrategyProperties)Params).TakeProfit1)
{
PlaceBuyMarketOrder(position.Security, decimal.Floor(0.33m * position.CurrentValue));
if (MyTrades.Any(t => t.Trade.Security.Code == Security.Code))
{
var myTradesOrderedByDate = MyTrades.ToList().OrderBy(t => t.Trade.Time);
var trade = myTradesOrderedByDate.Last(t => t.Trade.Security.Code == Security.Code);
var entryPrice = trade.Trade.Price;
((HustleEveryDayStrategyProperties)Params).Stoploss = entryPrice;
}
return;
}
}
}
}
}
private void CheckForExitByTimeTargets()
{
this.AddInfoLog("Выход по тайм-стопу");
foreach (var position in PositionManager.Positions)
{
if(position.CurrentValue>0)
{
PlaceSellMarketOrder(position.Security,position.CurrentValue);
}
if (position.CurrentValue < 0)
{
PlaceBuyMarketOrder(position.Security, -position.CurrentValue);
}
}
}
protected void PlaceBuyMarketOrder(Security security, decimal volume)
{
var order = this.BuyAtMarket(volume);
order.Security = security;
order
.WhenChanged()
.Do(() => this.AddInfoLog("Изменилось остояние заявки"))
.Once()
.Apply(this);
order
.WhenRegistered()
.Do(() => this.AddInfoLog("Заявка успешно зарегистрирована"))
.Once()
.Apply(this);
order
.WhenRegisterFailed()
.Do(() => this.AddInfoLog("Заявка не принята биржей"))
.Once()
.Apply(this);
order
.WhenMatched()
.Do(() =>
{
this.AddInfoLog("Заявка полностью исполнена");
})
.Once()
.Apply(this);
// регистрирация заявки
RegisterOrder(order);
}
protected void PlaceSellMarketOrder(Security security, decimal volume)
{
var order = this.SellAtMarket(volume);
order.Security = security;
order
.WhenChanged()
.Do(() => this.AddInfoLog("Изменилось остояние заявки"))
.Once()
.Apply(this);
order
.WhenRegistered()
.Do(() => this.AddInfoLog("Заявка успешно зарегистрирована"))
.Once()
.Apply(this);
order
.WhenRegisterFailed()
.Do(() => this.AddInfoLog("Заявка не принята биржей"))
.Once()
.Apply(this);
order
.WhenMatched()
.Do(() =>
{
this.AddInfoLog("Заявка полностью исполнена");
})
.Once()
.Apply(this);
// регистрирация заявки
RegisterOrder(order);
}
}
}
|
|
|
|
|
liftrade
|
Дата: 03.12.2013
Интересно, это только у меня в каркасе в таблице сделки, отображается только первая сделка? Никакие последующие в нее не заносятся... Или это общий баг такой?
|
|
Спасибо:
|
|
|
|
|
Kazai Mazai
|
Дата: 13.12.2013
liftrade Интересно, это только у меня в каркасе в таблице сделки, отображается только первая сделка? Никакие последующие в нее не заносятся... Или это общий баг такой? да у меня тоже был такой баг, почему-то insert не так работает, как хотелось бы. В StrategyDocument.xaml.cs меняем закомментированное на незакомментированное. Код
_strategy.NewMyTrades += trades =>
{
foreach (var trade in trades)
{
_tradeGrid.Trades.Add(trade.Trade);
//_tradeGrid.Trades.Insert(0, trade.Trade);
}
};
|
|
|
|