Наконец выстрадал эти несчастные подчеркивания))), неужели нет способа попроще? С моим уровнем кодинга это действительно было не просто. Могу Тслабу только пожелать подтягиваться за старшим братом))) в плане визуализации.
using System;
using System.Collections.Generic;
using TSLab.Script;
using TSLab.Script.Handlers;
using TSLab.Script.Optimization;
using TSLab.Script.Helpers;
namespace TSLab
{
public class TsLab : IExternalScript
{
public IPosition LastActivePosition = null;
#region Константы
#endregion
#region Параметры оптимизации
// период SMA
public OptimProperty StopSmaPeriod = new OptimProperty(20, 20, 200, 20);
#endregion
public virtual void Execute(IContext ctx, ISecurity symbol)
{
var firstValidValue = 0;
#region Индикаторы
var stopSma = ctx.GetData("sma", new string[] { StopSmaPeriod.ToString() },
() => Series.SMA(symbol.ClosePrices, StopSmaPeriod));
firstValidValue = Math.Max(firstValidValue, StopSmaPeriod);
// серия значений стоп-уровня
IList<double> stopPrice = new List<double>(symbol.Bars.Count);
#endregion
#region Переменные
double stopLoss = 0;
#endregion
#region основной цикл - проход по барам
for (int bar = 0; bar < symbol.Bars.Count; bar++)
{
if (bar < firstValidValue)
{
stopLoss = 0;
stopPrice.Add(stopLoss);
continue;
}
LastActivePosition = symbol.Positions.GetLastPositionActive(bar); // получить ссылку на последнию позицию
#region Сигналы на вход и выход
var isSignalBuy = symbol.ClosePrices[bar] > symbol.HighPrices[bar - 1];
isSignalBuy &= symbol.LowPrices[bar] > stopSma[bar];
var isSignaShort = symbol.ClosePrices[bar] < symbol.LowPrices[bar - 1];
isSignaShort &= symbol.HighPrices[bar] < stopSma[bar];
#endregion
#region Исполнение сигналов на вход
if (LastActivePosition == null) // Если позиции нет
{
stopLoss = 0;
if (isSignalBuy) // Если поступил сигнал на покупку
symbol.Positions.BuyAtMarket(bar + 1, 1, "LE"); // покупаем
else if (isSignaShort) // Если поступил сигнал на продажу
symbol.Positions.SellAtMarket(bar + 1, 1, "SE"); //продаем
}
#endregion
#region Сопровождение и выход
else // Если есть активная позиция
{
var barsHeld = bar - LastActivePosition.EntryBarNum + 1;
var smaPeriod = StopSmaPeriod - barsHeld;
smaPeriod = smaPeriod < 5 ? 5 : smaPeriod;
var adoptSma = ctx.GetData("sma", new string[] { smaPeriod.ToString() },
() => Series.SMA(symbol.ClosePrices, smaPeriod));
if (LastActivePosition.IsLong) //если позиция длинная
{
if (bar == LastActivePosition.EntryBarNum)
stopLoss = adoptSma[LastActivePosition.EntryBarNum - 1];
else
stopLoss = Math.Max(stopLoss, adoptSma[bar]); //"Ни шагу назад"
if(symbol.ClosePrices[bar] < stopLoss)
LastActivePosition.CloseAtPrice(bar + 1, symbol.ClosePrices[bar], "LX");
}
else //если позиция короткая
{
if (bar == LastActivePosition.EntryBarNum)
stopLoss = adoptSma[LastActivePosition.EntryBarNum - 1];
else
stopLoss = Math.Min(stopLoss, adoptSma[bar]); //"Ни шагу назад"
if (symbol.ClosePrices[bar] > stopLoss)
LastActivePosition.CloseAtPrice(bar + 1, symbol.ClosePrices[bar], "SX");
}
}
#endregion
stopPrice.Add(stopLoss);
}
#endregion
#region прорисовка графиков
var pane = ctx.CreatePane(symbol.ToString(), 100, false);
pane.UpdatePrecision(PaneSides.RIGHT, symbol.Decimals);
var color = new Color(System.Drawing.Color.Black.ToArgb());
pane.AddList(symbol.Symbol, symbol, CandleStyles.BAR_CANDLE, color, PaneSides.RIGHT);
color = new Color(System.Drawing.Color.Brown.ToArgb());
pane.AddList("StopLevel", stopPrice, ListStyles.POINT, color, LineStyles.SOLID, PaneSides.RIGHT);
color = new Color(System.Drawing.Color.Blue.ToArgb());
pane.AddList("SMA", stopSma, ListStyles.LINE, color, LineStyles.SOLID, PaneSides.RIGHT);
#endregion
}
}
}