StockSharp
294 строки · 8.0 Кб
1#region S# License2/******************************************************************************************
3NOTICE!!! This program and source code is owned and licensed by
4StockSharp, LLC, www.stocksharp.com
5Viewing or use of this code requires your acceptance of the license
6agreement found at https://github.com/StockSharp/StockSharp/blob/master/LICENSE
7Removal of this comment is a violation of the license agreement.
8
9Project: SampleHistoryTesting.SampleHistoryTestingPublic
10File: SmaStrategy.cs
11Created: 2015, 11, 11, 2:32 PM
12
13Copyright 2010 by StockSharp, LLC
14*******************************************************************************************/
15#endregion S# License16namespace SampleHistoryTesting17{
18using System;19using System.Linq;20using System.Collections.Generic;21
22using Ecng.Common;23
24using StockSharp.Algo;25using StockSharp.Algo.Indicators;26using StockSharp.Algo.Strategies;27using StockSharp.Logging;28using StockSharp.BusinessEntities;29using StockSharp.Messages;30using StockSharp.Localization;31using StockSharp.Charting;32using StockSharp.Algo.Strategies.Protective;33
34class SmaStrategy : Strategy35{36private readonly ProtectiveController _protectiveController = new();37private IProtectivePositionController _posController;38
39private IChart _chart;40
41private readonly List<MyTrade> _myTrades = new();42private bool? _isShortLessThenLong;43private SimpleMovingAverage _shortSma;44private SimpleMovingAverage _longSma;45
46private IChartCandleElement _chartCandlesElem;47private IChartTradeElement _chartTradesElem;48private IChartIndicatorElement _chartLongElem;49private IChartIndicatorElement _chartShortElem;50
51public SmaStrategy()52{53_longSmaParam = this.Param(nameof(LongSma), 80);54_shortSmaParam = this.Param(nameof(ShortSma), 30);55_takeValue = this.Param(nameof(TakeValue), new Unit(1, UnitTypes.Percent));56_stopValue = this.Param(nameof(StopValue), new Unit(2, UnitTypes.Percent));57_candleTypeParam = this.Param(nameof(CandleType), DataType.TimeFrame(TimeSpan.FromMinutes(1))).NotNull();58_candleTimeFrameParam = this.Param<TimeSpan?>(nameof(CandleTimeFrame));59_buildFromParam = this.Param<DataType>(nameof(BuildFrom));60_buildFieldParam = this.Param<Level1Fields?>(nameof(BuildField));61}62
63private readonly StrategyParam<TimeSpan?> _candleTimeFrameParam;64
65public TimeSpan? CandleTimeFrame66{67get => _candleTimeFrameParam.Value;68set => _candleTimeFrameParam.Value = value;69}70
71private readonly StrategyParam<int> _longSmaParam;72
73public int LongSma74{75get => _longSmaParam.Value;76set => _longSmaParam.Value = value;77}78
79private readonly StrategyParam<int> _shortSmaParam;80
81public int ShortSma82{83get => _shortSmaParam.Value;84set => _shortSmaParam.Value = value;85}86
87private readonly StrategyParam<DataType> _candleTypeParam;88
89public DataType CandleType90{91get => _candleTypeParam.Value;92set => _candleTypeParam.Value = value;93}94
95private readonly StrategyParam<DataType> _buildFromParam;96
97public DataType BuildFrom98{99get => _buildFromParam.Value;100set => _buildFromParam.Value = value;101}102
103private readonly StrategyParam<Level1Fields?> _buildFieldParam;104
105public Level1Fields? BuildField106{107get => _buildFieldParam.Value;108set => _buildFieldParam.Value = value;109}110
111private readonly StrategyParam<Unit> _takeValue;112
113public Unit TakeValue114{115get => _takeValue.Value;116set => _takeValue.Value = value;117}118
119private readonly StrategyParam<Unit> _stopValue;120
121public Unit StopValue122{123get => _stopValue.Value;124set => _stopValue.Value = value;125}126
127protected override void OnReseted()128{129base.OnReseted();130
131_protectiveController.Clear();132_posController = default;133}134
135protected override void OnStarted(DateTimeOffset time)136{137base.OnStarted(time);138
139// !!! DO NOT FORGET add it in case use IsFormed property (see code below)140Indicators.Add(_longSma = new SimpleMovingAverage { Length = LongSma });141Indicators.Add(_shortSma = new SimpleMovingAverage { Length = ShortSma });142
143_chart = this.GetChart();144
145if (_chart != null)146{147var area = _chart.AddArea();148
149_chartCandlesElem = area.AddCandles();150_chartTradesElem = area.AddTrades();151_chartShortElem = area.AddIndicator(_shortSma);152_chartLongElem = area.AddIndicator(_longSma);153
154// make short line coral color155_chartShortElem.Color = System.Drawing.Color.Coral;156}157
158var dt = CandleType;159
160if (CandleTimeFrame is not null)161{162dt = DataType.Create(dt.MessageType, CandleTimeFrame);163}164
165var subscription = new Subscription(dt, Security)166{167MarketData =168{169IsFinishedOnly = true,170BuildFrom = BuildFrom,171BuildMode = BuildFrom is null ? MarketDataBuildModes.LoadAndBuild : MarketDataBuildModes.Build,172BuildField = BuildField,173}174};175
176subscription
177.WhenCandleReceived(this)178.Do(ProcessCandle)179.Apply(this);180
181this182.WhenNewMyTrade()183.Do(t =>184{185_myTrades.Add(t);186
187var security = t.Order.Security;188var portfolio = t.Order.Portfolio;189
190if (TakeValue.IsSet() || StopValue.IsSet())191{192_posController ??= _protectiveController.GetController(193security.ToSecurityId(),194portfolio.Name,195new LocalProtectiveBehaviourFactory(security.PriceStep, security.Decimals),196TakeValue, StopValue, true, true, default, default, true);197}198
199var info = _posController?.Update(t.Trade.Price, t.GetPosition());200
201if (info is not null)202ActiveProtection(info.Value);203})204.Apply(this);205
206_isShortLessThenLong = null;207
208Subscribe(subscription);209}210
211private void ProcessCandle(ICandleMessage candle)212{213// strategy are stopping214if (ProcessState == ProcessStates.Stopping)215{216CancelActiveOrders();217return;218}219
220this.AddInfoLog(LocalizedStrings.SmaNewCandleLog, candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice, candle.TotalVolume, candle.SecurityId);221
222// try activate local stop orders (if they present)223var info = _posController?.TryActivate(candle.ClosePrice, CurrentTime);224
225if (info is not null)226ActiveProtection(info.Value);227
228// process new candle229var longValue = _longSma.Process(candle);230var shortValue = _shortSma.Process(candle);231
232// all indicators added in OnStarted now is fully formed and we can use it233// or user turned off allow trading234if (this.IsFormedAndOnlineAndAllowTrading())235{236// in case we subscribed on non finished only candles237if (candle.State == CandleStates.Finished)238{239// calc new values for short and long240var isShortLessThenLong = shortValue.GetValue<decimal>() < longValue.GetValue<decimal>();241
242if (_isShortLessThenLong == null)243{244_isShortLessThenLong = isShortLessThenLong;245}246else if (_isShortLessThenLong != isShortLessThenLong) // crossing happened247{248// if short less than long, the sale, otherwise buy249var direction = isShortLessThenLong ? Sides.Sell : Sides.Buy;250
251// calc size for open position or revert252var volume = Position == 0 ? Volume : Position.Abs().Min(Volume) * 2;253
254// calc order price as a close price255var price = candle.ClosePrice;256
257RegisterOrder(this.CreateOrder(direction, price, volume));258
259// or revert position via market quoting260//var strategy = new MarketQuotingStrategy(direction, volume);261//ChildStrategies.Add(strategy);262
263// store current values for short and long264_isShortLessThenLong = isShortLessThenLong;265}266}267}268
269var trade = _myTrades.FirstOrDefault();270_myTrades.Clear();271
272if (_chart == null)273return;274
275var data = _chart.CreateData();276
277data
278.Group(candle.OpenTime)279.Add(_chartCandlesElem, candle)280.Add(_chartShortElem, shortValue)281.Add(_chartLongElem, longValue)282.Add(_chartTradesElem, trade)283;284
285_chart.Draw(data);286}287
288private void ActiveProtection((bool isTake, Sides side, decimal price, decimal volume, OrderCondition condition) info)289{290// sending protection (=closing position) order as regular order291RegisterOrder(this.CreateOrder(info.side, info.price, info.volume));292}293}294}