TheRoman:
Я бы ещё предложил интеграцию с кодом wealth-lab, языки как раз у них одинаковый, можно дравину сделать с аналичными функциями wealth-lab-а, что бы просто можно было копировасть код с wealth-lab в #stocksharp и обратно.
Я для этого использую независимую от внешней инфраструктуры библиотеку, которая на вход принимает ghost-bar, а на выходе выдает сигналы для покупки/продажи.
Реализация библиотеки по сути является абстрактной системой анализа. Сам торговый алгоритм пишется в терминах этой системы.
Далее эту библиотеку можно легко интегрировать с любой системой анализа или риал-тайм торговли:
Интерфейс сигнальной машины (основной объект абстрактной системы анализа):
public interface IStrategyPackage
{
IList<ISignalStrategy> Items { get; }
void Setup();
SignalSet Process(TimeFrameCandle ghostCandle);
StopSet GetStops();
}
Интеграция с S#:
class StockSharpStrategy {
...
protected override ProcessResults OnProcess()
{
// если наша стратегия в процессе остановки
if (ProcessState == ProcessStates.Stopping)
{
// отменяем активные заявки
CancelActiveOrders();
// так как все активные заявки гарантированно были отменены, то возвращаем ProcessResults.Stop
return ProcessResults.Stop;
}
TimeFrameCandle candle = candleManager.GetCurrentTimeFrameCandle(Security, TimeFrame);
if (candle != null)
{
lock (locker)
{
ProcessSignals(candle);
}
}
return ProcessResults.Continue;
}
private void ProcessSignals(TimeFrameCandle candle)
{
var signalSet = signalMachine.Process(candle);
foreach (var signal in signalSet.Open)
{
if (signal.Alarm)
{
var direction = signal.PositionType == SignalPositionType.Long
? OrderDirections.Buy
: OrderDirections.Sell;
RegisterOrder(direction);
}
}
foreach (var signal in signalSet.Close)
{
if (signal.Alarm)
{
var direction = signal.PositionType == SignalPositionType.Long
? OrderDirections.Sell
: OrderDirections.Buy;
RegisterOrder(direction);
}
}
}
...
}
Интеграция с Wealth-lab:
public abstract class WealthStrategy : WealthScript
{
protected override void Execute()
{
...
for (int bar = 1; bar < Bars.Count; bar++)
{
TimeFrameCandle candle = Bars.ToCandle(bar);
var signalSet = signalMachine.Process(candle);
ProcessSignals(bar, signalSet);
var stops = signalMachine.GetStops();
if (bar < Bars.Count - 1)
{
DrawStops(bar, stops);
}
}
}
protected void ProcessSignals(int bar, SignalSet signalSet)
{
foreach (Signal signal in signalSet.Open)
{
if (signal.Alarm)
{
OpenPosition(bar, signal);
}
}
foreach (Signal signal in signalSet.Close)
{
if (signal.Alarm)
{
ClosePosition(bar, signal);
}
}
}
private void OpenPosition(int bar, Signal signal)
{
if (signal.PositionType == SignalPositionType.Long)
{
if (signal.OrderType == SignalOrderType.AtOpen)
{
BuyAtMarket(bar);
}
if (signal.OrderType == SignalOrderType.StopLoss)
{
BuyAtStop(bar, signal.Price);
}
if (signal.OrderType == SignalOrderType.TakeProfit)
{
BuyAtLimit(bar, signal.Price);
}
}
if (signal.PositionType == SignalPositionType.Short)
{
if (signal.OrderType == SignalOrderType.AtOpen)
{
ShortAtMarket(bar);
}
if (signal.OrderType == SignalOrderType.StopLoss)
{
ShortAtStop(bar, signal.Price);
}
if (signal.OrderType == SignalOrderType.TakeProfit)
{
ShortAtLimit(bar, signal.Price);
}
}
}