Пример стратегии Пересечение скользящих средних

using System;
using System.Collections.Generic;
using System.Linq;
using TSLab.Script;
using TSLab.Script.Handlers;
using TSLab.Script.Helpers;
using TSLab.Script.Optimization;

namespace MyLib
{
    public class CrossMA : IExternalScript
    {
        // Параметры оптимизации
        public OptimProperty PeriodFast = new OptimProperty(10, 10, 50, 5);
        public OptimProperty PeriodSlow = new OptimProperty(50, 50, 200, 10);

        // Метод обработки, запускается при пересчете скрипта
        public virtual void Execute(IContext ctx, ISecurity sec)
        {
            // Вычисляем быструю и медленную SMA
            // Используем GetData для кеширования данных и ускорения оптимизации
            var smaSlow = ctx.GetData("SMA", new[] { PeriodSlow.ToString() },
                () => Series.SMA(sec.GetClosePrices(ctx), PeriodSlow));
            var smaFast = ctx.GetData("SMA", new[] { PeriodFast.ToString() },
                () => Series.SMA(sec.GetClosePrices(ctx), PeriodFast));

            // Если последняя свеча до конца не сформировалась, ее не нужно использовать в цикле торговли
            var barsCount = sec.Bars.Count;
            if (!ctx.IsLastBarUsed)
            {
                barsCount--;
            }

            var startBar = Math.Max(PeriodSlow, ctx.TradeFromBar);

            // Торговля
            for (int i = startBar; i < barsCount; i++)
            {
                // Вычисляем сигналы
                var sLong = smaFast[i] > smaSlow[i] && smaFast[i - 1] <= smaSlow[i - 1];
                var sShort = smaFast[i] < smaSlow[i] && smaFast[i - 1] >= smaSlow[i - 1];

                // Получаем активные позиции
                var posLong = sec.Positions.GetLastActiveForSignal("LE", i);
                var posShort = sec.Positions.GetLastActiveForSignal("SE", i);

                if (posLong == null)
                {
                    // Если нет активной длинной позиции и есть сигнал на покупку, то покупаем по рынку
                    if (sLong)
                    {
                        sec.Positions.BuyAtMarket(i + 1, 1, "LE");
                    }
                }
                else
                {
                    // Если есть длинная позиция и есть сигнал на продажу, то закрывам лонг по рынку
                    if (sShort)
                    {
                        posLong.CloseAtMarket(i + 1, "LX");
                    }
                }


                if (posShort == null)
                {
                    // Если нет активной короткой позиции и есть сигнал на продажу, то продаем по рынку
                    if (sShort)
                    {
                        sec.Positions.SellAtMarket(i + 1, 1, "SE");
                    }
                }
                else
                {
                    // Если есть короткая позиция и есть сигнал на покупку, то закрываем шорт по рынку
                    if (sLong)
                    {
                        posShort.CloseAtMarket(i + 1, "SX");
                    }
                }
            }

            // Если идет процесс оптимизации, то графики рисовать не нужно, это замедляет работу
            if (ctx.IsOptimization)
            {
                return;
            }

            // Отрисовка графиков
            ctx.First.AddList(string.Format("SMAFast({0})", PeriodFast), smaFast, ListStyles.LINE, ScriptColors.Green,
                LineStyles.SOLID, PaneSides.RIGHT);
            ctx.First.AddList(string.Format("SMASlow({0})", PeriodSlow), smaSlow, ListStyles.LINE, ScriptColors.Red,
                LineStyles.SOLID, PaneSides.RIGHT);
        }
    }
}

Last updated