namespace Ecng.Trading.Algo.Testing
{
using System;
using System.Collections.Generic;
using Ecng.Trading.BusinessEntities;
using Ecng.Common;
///
/// Настройки генератора стакана.
///
public class MarketDepthGeneratorSettings : GeneratorSettings
{
///
/// Создать .
///
public MarketDepthGeneratorSettings()
{
this.MaxBidsDepth = 10;
this.MaxAsksDepth = 10;
}
///
/// Максимальная глубина бидов.
///
///
/// Значение по умолчанию равно 10.
///
public int MaxBidsDepth { get; set; }
///
/// Максимальная глубина офферов.
///
///
/// Значение по умолчанию равно 10.
///
public int MaxAsksDepth { get; set; }
}
///
/// Генератор стакана случайным методом.
///
public class MarketDepthGenerator
{
///
/// Создать .
///
public MarketDepthGenerator()
{
this.Settings = new MarketDepthGeneratorSettings();
}
///
/// Настройки генератора.
///
public MarketDepthGeneratorSettings Settings { get; private set; }
///
/// Получить стартовую цену, относительно которой будет производится генерация стакана.
///
/// Инструмент.
/// Стартовая цена.
public virtual double GetSeedPrice(Security security)
{
if (security == null)
throw new ArgumentNullException("security");
double seedPrice = 0;
if (security.LastTrade.Price != 0)
seedPrice = security.LastTrade.Price;
else if (security.BestBid.Price != 0)
seedPrice = security.BestBid.Price + security.BestPair.SpreadPrice / 2;
else if (security.BestAsk.Price != 0)
seedPrice = security.BestAsk.Price - security.BestPair.SpreadPrice / 2;
else if (security.ClosePrice != 0)
seedPrice = security.ClosePrice;
else if (security.OpenPrice != 0)
seedPrice = security.OpenPrice;
if (seedPrice == 0)
throw new ArgumentException("Инструмент содержит недостаточно информации для генерации стакана.", "security");
return seedPrice + RandomGen.GetInt(-this.Settings.MaxPriceStepCount, this.Settings.MaxPriceStepCount) * security.MinStepSize;
}
///
/// Сгенерировать стакан.
///
/// Инструмент, стакан для которого необходимо сгенерировать.
/// Сгенерированный стакан.
public virtual MarketDepth Generate(Security security)
{
var marketDepth = new MarketDepth(security);
Generate(marketDepth);
return marketDepth;
}
///
/// Сгенерировать стакан.
///
/// Стакан с котировками, которые необходимо обновить случайным образом.
/// Сгенерированный стакан.
public virtual void Generate(MarketDepth depth)
{
if (depth == null)
throw new ArgumentNullException("depth");
var bids = new List();
var asks = new List();
var seedPrice = GetSeedPrice(depth.Security);
var lastBidPrice = seedPrice;
var lastAskPrice = seedPrice;
for (var i = 0; i < this.Settings.MaxBidsDepth; i++)
{
var quote = CreateQuote(lastBidPrice, depth.Security, OrderDirections.Buy);
if (quote.Price <= 0)
break;
bids.Add(quote);
lastBidPrice = quote.Price;
}
for (var i = 0; i < this.Settings.MaxAsksDepth; i++)
{
var quote = CreateQuote(lastAskPrice, depth.Security, OrderDirections.Sell);
if (quote.Price <= 0)
break;
asks.Add(quote);
lastAskPrice = quote.Price;
}
depth.Update(bids, asks, true);
}
private Quote CreateQuote(double startPrice, Security security, OrderDirections direction)
{
if (security == null)
throw new ArgumentNullException("security");
if (security.MinStepSize == 0)
throw new ArgumentException("Минимальный шаг цены не может быть равен 0.", "security");
return new Quote
{
OrderDirection = direction,
Price = security.ShrinkPrice(startPrice + (direction == OrderDirections.Sell ? 1 : -1) * (RandomGen.GetInt(1, this.Settings.MaxPriceStepCount) * security.MinStepSize)),
Security = security,
Volume = RandomGen.GetInt(1, this.Settings.MaxVolume),
};
}
}
}