QUANTOWER - 如何访问量化策略中的自定义指标?

问题描述 投票:0回答:0

这是我的自定义指标,它只是修改后的 TDI 指标:

using System.Drawing;
using System.Linq;
using TradingPlatform.BusinessLayer;

namespace Trend
{
    public class Sniper : Indicator, IWatchlistIndicator
    {
        #region Parameters
        [InputParameter("RSI period", 10, 1, 9999)]
        public int Period = 13;

        [InputParameter("Sources prices for the RSI line", 20, variants: new object[] {
             "Close", PriceType.Close,
             "Open", PriceType.Open,
             "High", PriceType.High,
             "Low", PriceType.Low,
             "Typical", PriceType.Typical,
             "Medium", PriceType.Median,
             "Weighted", PriceType.Weighted,
             "Volume", PriceType.Volume,
             "Open interest", PriceType.OpenInterest
        })]
        public PriceType SourcePrice = PriceType.Close;

        [InputParameter("Type of the RSI line", 30, variants: new object[] {
             "Simple", RSIMode.Simple,
             "Exponential", RSIMode.Exponential}
        )]
        public RSIMode RSIMode = RSIMode.Exponential;

        [InputParameter("Volatility Band", 40, 1, 999)]
        public int VolatilityBand = 34;
        [InputParameter("Standard Deviation", 50, 0.1, 100.0, 0.1, 2)]
        public double StandardDeviation = 1.6185;

        [InputParameter("Fast MA period on RSI", 60, 1, 9999)]
        public int FastMaOnRSIPeriod = 2;

        [InputParameter("Fast MA type on RSI", 60, variants: new object[] {
            "Simple", MaMode.SMA,
            "Exponential", MaMode.EMA,
            "Smoothed Modified", MaMode.SMMA,
            "Linear Weighted", MaMode.LWMA}
        )]
        public MaMode FastMAOnRSIMode = MaMode.SMA;

        //
        [InputParameter("Calculation type", 90, variants: new object[]
        {
            "All available data", IndicatorCalculationType.AllAvailableData,
            "By period", IndicatorCalculationType.ByPeriod,
        })]
        public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE;

        #endregion Parameters

        private Indicator rsi;
        private Indicator bb;
        private HistoricalDataCustom historicalDataBB;
        private Indicator priceMa;
        private HistoricalDataCustom historicalDataPrice;

        public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorTradersDynamicIndex.cs";

        /// <summary>
        /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 
        /// </summary>
        public Sniper()
            : base()
        {
            // Defines indicator's name and description.
            Name = "Sniper";
            Description = "";

            // Defines line on demand with particular parameters.
            AddLineSeries("BB Up", Color.Orange, 1, LineStyle.Solid);
            AddLineSeries("BB Down", Color.Orange, 1, LineStyle.Solid);
            AddLineSeries("Fast MA on RSI", Color.White, 1, LineStyle.Solid);

            AddLineLevel(68, "", Color.Gray, 1, LineStyle.Dash);
            AddLineLevel(32, "", Color.Gray, 1, LineStyle.Dash);

            SeparateWindow = true;
        }

        public int MinHistoryDepths => Enumerable.Max(new int[] { VolatilityBand, FastMaOnRSIPeriod }) + Period;
        public override string ShortName => $"Sniper ({Period}: {VolatilityBand}: {FastMaOnRSIPeriod})";

        /// <summary>
        /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates.
        /// </summary>
        protected override void OnInit()
        {
            rsi = Core.Indicators.BuiltIn.RSI(Period, SourcePrice, RSIMode, MaMode.SMA, 1);

            bb = Core.Indicators.BuiltIn.BB(VolatilityBand, StandardDeviation, PriceType.Close, MaMode.SMA);
            historicalDataBB = new HistoricalDataCustom(this);
            historicalDataBB.AddIndicator(bb);

            priceMa = Core.Indicators.BuiltIn.MA(FastMaOnRSIPeriod, PriceType.Close, FastMAOnRSIMode, this.CalculationType);
            historicalDataPrice = new HistoricalDataCustom(this);
            historicalDataPrice.AddIndicator(priceMa);

            AddIndicator(rsi);
        }

        /// <summary>
        /// Calculation entry point. This function is called when a price data updates. 
        /// Will be runing under the HistoricalBar mode during history loading. 
        /// Under NewTick during realtime. 
        /// Under NewBar if start of the new bar is required.
        /// </summary>
        /// <param name="args">Provides data of updating reason and incoming price.</param>
        protected override void OnUpdate(UpdateArgs args)
        {
            if (this.Count < this.Period)
                return;

            historicalDataBB[PriceType.Close] = rsi.GetValue();
            historicalDataPrice[PriceType.Close] = rsi.GetValue();
            double fastMAonRSI = priceMa.GetValue();
            double bbUp = bb.GetValue(0, 0);
            double bbDown = bb.GetValue(0, 2);

            if (this.Count < this.MinHistoryDepths)
                return;

            SetValue(bbUp, 0);
            SetValue(bbDown, 1);
            SetValue(fastMAonRSI, 2);

            if (fastMAonRSI > bbUp)
            {
                LinesSeries[2].SetMarker(0, new IndicatorLineMarker(Color.Red, upperIcon: IndicatorLineMarkerIconType.DownArrow));
            }
            else if(fastMAonRSI < bbDown)
            {
                LinesSeries[2].SetMarker(0, new IndicatorLineMarker(Color.Green, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
            }
            else
            {
                LinesSeries[2].RemoveMarker(0);
            }
        }
    }
}

这是我的策略:

// Copyright QUANTOWER LLC. © 2017-2022. All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using TradingPlatform.BusinessLayer;

namespace Scalpie
{
    public class Scalpie : Strategy, ICurrentAccount, ICurrentSymbol
    {
        [InputParameter("Symbol", 0)]
        public Symbol CurrentSymbol { get; set; }

        /// <summary>
        /// Account to place orders
        /// </summary>
        [InputParameter("Account", 1)]
        public Account CurrentAccount { get; set; }

        /// <summary>
        /// Period to load history
        /// </summary>
        [InputParameter("Period", 5)]
        private Period period = Period.MIN5;

        /// <summary>
        /// Period for Fast MA indicator
        /// </summary>
        [InputParameter("Fast MA", 2, minimum: 1, maximum: 100, increment: 1, decimalPlaces: 0)]
        public int FastMA = 5;

        /// <summary>
        /// Period for Slow MA indicator
        /// </summary>
        [InputParameter("Slow MA", 3, minimum: 1, maximum: 100, increment: 1, decimalPlaces: 0)]
        public int SlowMA = 10;

        /// <summary>
        /// Quantity to open order
        /// </summary>
        [InputParameter("Quantity", 4, 0.1, 99999, 0.1, 2)]
        public double Quantity = 1.0;

        public override string[] MonitoringConnectionsIds => new string[] { this.CurrentSymbol?.ConnectionId, this.CurrentAccount?.ConnectionId };

        private Indicator indicatorFastMA;
        private Indicator indicatorSlowMA;

        private HistoricalData hdm;

        private int longPositionsCount;
        private int shortPositionsCount;
        private string orderTypeId;

        private bool waitOpenPosition;
        private bool waitClosePositions;

        public Scalpie()
            : base()
        {
            this.Name = "Scalpie";
            this.Description = "scalping strat automated";
        }

        protected override void OnRun()
        {
            this.Log("Test message");
            // Restore account object from acive connection
            if (this.CurrentAccount != null && this.CurrentAccount.State == BusinessObjectState.Fake)
                this.CurrentAccount = Core.Instance.GetAccount(this.CurrentAccount.CreateInfo());

            // Restore symbol object from acive connection
            if (this.CurrentSymbol != null && this.CurrentSymbol.State == BusinessObjectState.Fake)
                this.CurrentSymbol = Core.Instance.GetSymbol(this.CurrentSymbol.CreateInfo());

            if (this.CurrentSymbol == null || this.CurrentAccount == null || this.CurrentSymbol.ConnectionId != this.CurrentAccount.ConnectionId)
            {
                this.Log("Incorrect input parameters... Symbol or Account are not specified or they have different connectionID.", StrategyLoggingLevel.Error);
                return;
            }

            this.orderTypeId = Core.OrderTypes.FirstOrDefault(x => x.ConnectionId == this.CurrentSymbol.ConnectionId && x.Behavior == OrderTypeBehavior.Market).Id;

            if (string.IsNullOrEmpty(this.orderTypeId))
            {
                this.Log("Connection of selected symbol has not support market orders", StrategyLoggingLevel.Error);
                return;
            }

            this.indicatorFastMA = Core.Instance.Indicators.BuiltIn.SMA(this.FastMA, PriceType.Close);
            this.indicatorSlowMA = Core.Instance.Indicators.BuiltIn.SMA(this.SlowMA, PriceType.Close);

            this.hdm = this.CurrentSymbol.GetHistory(this.period, this.CurrentSymbol.HistoryType, Core.TimeUtils.DateTimeUtcNow.AddDays(-100));

            Core.PositionAdded += this.Core_PositionAdded;
            Core.PositionRemoved += this.Core_PositionRemoved;

            Core.OrdersHistoryAdded += this.Core_OrdersHistoryAdded;

            this.hdm.HistoryItemUpdated += this.Hdm_HistoryItemUpdated;

            this.hdm.AddIndicator(this.indicatorFastMA);
            this.hdm.AddIndicator(this.indicatorSlowMA);
        }

        protected override void OnStop()
        {
            Core.PositionAdded -= this.Core_PositionAdded;
            Core.PositionRemoved -= this.Core_PositionRemoved;

            Core.OrdersHistoryAdded -= this.Core_OrdersHistoryAdded;

            if (this.hdm != null)
            {
                this.hdm.HistoryItemUpdated -= this.Hdm_HistoryItemUpdated;
                this.hdm.Dispose();
            }

            base.OnStop();
        }

        protected override List<StrategyMetric> OnGetMetrics()
        {
            var result = base.OnGetMetrics();

            // An example of adding custom strategy metrics:
            result.Add("Total long positions", this.longPositionsCount.ToString());
            result.Add("Total short positions", this.shortPositionsCount.ToString());

            return result;
        }

        private void Core_PositionAdded(Position obj)
        {
            var positions = Core.Instance.Positions.Where(x => x.Symbol == this.CurrentSymbol && x.Account == this.CurrentAccount).ToArray();
            this.longPositionsCount = positions.Count(x => x.Side == Side.Buy);
            this.shortPositionsCount = positions.Count(x => x.Side == Side.Sell);

            double currentPositionsQty = positions.Sum(x => x.Side == Side.Buy ? x.Quantity : -x.Quantity);

            if (Math.Abs(currentPositionsQty) == this.Quantity)
                this.waitOpenPosition = false;
        }

        private void Core_PositionRemoved(Position obj)
        {
            var positions = Core.Instance.Positions.Where(x => x.Symbol == this.CurrentSymbol && x.Account == this.CurrentAccount).ToArray();
            this.longPositionsCount = positions.Count(x => x.Side == Side.Buy);
            this.shortPositionsCount = positions.Count(x => x.Side == Side.Sell);

            if (!positions.Any())
                this.waitClosePositions = false;
        }

        private void Core_OrdersHistoryAdded(OrderHistory obj)
        {
            if (obj.Symbol == this.CurrentSymbol)
                return;

            if (obj.Account == this.CurrentAccount)
                return;

            if (obj.Status == OrderStatus.Refused)
                this.ProcessTradingRefuse();
        }

        private void Hdm_HistoryItemUpdated(object sender, HistoryEventArgs e) => this.OnUpdate();

        private void OnUpdate()
        {
            var positions = Core.Instance.Positions.Where(x => x.Symbol == this.CurrentSymbol && x.Account == this.CurrentAccount).ToArray();

            if (this.waitOpenPosition)
                return;

            if (this.waitClosePositions)
                return;


            this.Log("Test message");
            
            if (positions.Any())
            {
                if (this.indicatorFastMA.GetValue(1) < this.indicatorSlowMA.GetValue(1) || this.indicatorFastMA.GetValue(1) > this.indicatorSlowMA.GetValue(1))
                {
                    this.waitClosePositions = true;
                    this.Log($"Start close positions ({positions.Length})");

                    foreach (var item in positions)
                    {
                        var result = item.Close();

                        if (result.Status == TradingOperationResultStatus.Failure)
                            this.ProcessTradingRefuse();
                        else
                            this.Log($"Position was close: {result.Status}", StrategyLoggingLevel.Trading);
                    }
                }
            }
            else
            {
                if (this.indicatorFastMA.GetValue(2) < this.indicatorSlowMA.GetValue(2) && this.indicatorFastMA.GetValue(1) > this.indicatorSlowMA.GetValue(1))
                {
                    this.waitOpenPosition = true;
                    this.Log("Start open buy position");
                    //var result = Core.Instance.PlaceOrder(new PlaceOrderRequestParameters()
                    //{
                    //    Account = this.CurrentAccount,
                    //    Symbol = this.CurrentSymbol,

                    //    OrderTypeId = this.orderTypeId,
                    //    Quantity = this.Quantity,
                    //    Side = Side.Buy,
                    //});

                    //if (result.Status == TradingOperationResultStatus.Failure)
                    //    this.ProcessTradingRefuse();
                    //else
                    //    this.Log($"Position open: {result.Status}", StrategyLoggingLevel.Trading);
                }
                else if (this.indicatorFastMA.GetValue(2) > this.indicatorSlowMA.GetValue(2) && this.indicatorFastMA.GetValue(1) < this.indicatorSlowMA.GetValue(1))
                {
                    this.waitOpenPosition = true;
                    this.Log("Start open sell position");
                    //var result = Core.Instance.PlaceOrder(new PlaceOrderRequestParameters()
                    //{
                    //    Account = this.CurrentAccount,
                    //    Symbol = this.CurrentSymbol,

                    //    OrderTypeId = this.orderTypeId,
                    //    Quantity = this.Quantity,
                    //    Side = Side.Sell,
                    //});

                    //if (result.Status == TradingOperationResultStatus.Failure)
                    //    this.ProcessTradingRefuse();
                    //else
                    //    this.Log($"Position open: {result.Status}", StrategyLoggingLevel.Trading);
                }
            }
        }

        private void ProcessTradingRefuse()
        {
            this.Log("Strategy have received refuse for trading action. It should be stopped", StrategyLoggingLevel.Error);
            this.Stop();
        }
    }
}

我想将我的指标值纳入我的策略。请帮助。

我试图只实例化指标的类名,但它说它是未定义的。 智能感知对我大喊大叫。我还尝试复制策略文件中的指标代码,但没有任何结果。

c# quantitative-finance indicator
© www.soinside.com 2019 - 2024. All rights reserved.