Создание роботов с помощью S#. Часть 2. Базовый класс для всех стратегий
							
							
						 
						
						
						
						
	
			Все наши стратегии будем наследовать от класса StandardStrategy. Зачем он нужен? Дело в том, что все стратегии часто должны уметь делать одни и теже вещи: брать откуда-то торговую систему, портфель, инструмент, исторические свечки, хранить состояние, устанавливать  размер позиции. Чтобы не решать каждый раз эти проблемы, можно сделать так:
Код
	public abstract class StandardStrategy : Strategy
	{
		public virtual string Description { get { return Name; } }
		public ITraderBuilder TraderBuilder { get; set; }
		public IPortfolioSelector PortfolioSelector { get; set; }
		public ISecuritySelector SecuritySelector { get; set; }
		public IVolumeSizer VolumeSizer { get; set; }
		public IHistoryCandleProvider HistoryCandleProvider { get; set; }
		public ISettingsProvider SettingsProvider { get; set; }
		public Unit PriceDelta { get; set; }
		protected StandardStrategy()
		{
			PriceDelta = 0.1.Percents();
		}
	}
 ITraderBuilder будет  уметь волшебным образом создавать торговую систему:
Код
	public interface ITraderBuilder : IDisposable
	{
		string Title { get; }
		ITrader Trader { get; }
		ICandleManager CandleManager { get; }
		void RunTerminal();
		ITrader BuildTrader();
		event Action IsConnectedChanged;
	}
 IPortfolioSelector будет находить портфель:
Код
	public interface IPortfolioSelector
	{
		string Title { get; }
		Portfolio GetPortfolio(ITrader trader);
	}
 ISecuritySelector находить инструмент:
Код
	public interface ISecuritySelector
	{
		string Title { get; }
		Security GetSecurity(ITrader trader);
	}
 IVolumeSizer расчитывать размер позиции:
Код
	public interface IVolumeSizer
	{
		int GetVolume(Portfolio portfolio, Security security);
	}
 IHistoryCandleProvider получать исторические свечки:
Код
	public interface IHistoryCandleProvider
	{
		List<TimeFrameCandle> GetHistoryCandles(DateTime beginDate, DateTime endDate);
	}
 ISettingsProvider хранить состояние стратегии:
Код
	public interface ISettingsProvider
	{
		string ReadSetting(string name);
		void WriteSetting(string name, string value);
	}
 Представим, что у нас уже есть реалзации всех этих интерфесов (этим мы займемся позже). Как будет выглядить конкретная стратегия?
Код
	public class StrikeStrategy : StandardStrategy
	{
		public override string Description
		{
			get { return "Стратегия для ловли ударного дня"; }
		}
		CandleToken candleToken;
		DateTime strategyStartTime;
		public TimeSpan TimeFrame { get; set; }
		public StrikeStrategy()
		{
			TimeFrame = TimeSpan.FromMinutes(5);
		}
		protected override void OnStarting()
		{
			try
			{
				Trader = TraderBuilder.BuildTrader();
				if (Trader == null)
					throw new ApplicationException(string.Format("Отсутствует трейдер {0}.", TraderBuilder.Title));
				strategyStartTime = Trader.MarketTime;
				Portfolio = PortfolioSelector.GetPortfolio(Trader);
				if (Portfolio == null)
					throw new ApplicationException(string.Format("Отсутствует портфель {0}.", PortfolioSelector.Title));
				Security = SecuritySelector.GetSecurity(Trader);
				if (this.Security == null)
					throw new ApplicationException(string.Format("Отсутствует инструмент {0}.", SecuritySelector.Title));
				Trader.RegisterQuotes(Security);
				if (VolumeSizer != null)
				{
					Volume = VolumeSizer.GetVolume(Portfolio, Security);
					this.AddInfoLog("Объем: {0}", Volume);
				}
				if (TraderBuilder.CandleManager.IsTimeFrameCandlesRegistered(Security, TimeFrame))
				{
					candleToken = TraderBuilder.CandleManager.GetToken(typeof(TimeFrameCandle), Security, TimeFrame);
				}
				else
				{
					candleToken = TraderBuilder.CandleManager.RegisterTimeFrameCandles(Security, TimeFrame);
				}
				this.When(candleToken.CandlesFinished())
					.Do<IEnumerable<Candle>>(OnCandlesFinished);
			}
			catch (ApplicationException ex)
			{
				this.AddErrorLog(ex.Message);
			}
			base.OnStarting();
		}
		void OnCandlesFinished(IEnumerable<Candle> newCandles)
		{
			foreach (Candle candle in newCandles)
			{
				OnCandleFinished(candle);
			}
		}
		void OnCandleFinished(Candle candle)
		{
			DateTime currentDate = candle.Time;
			if (candle.Time < strategyStartTime)
				return;
			...
		}
	}
 Автор статьи — Вадим Чижов