0
Not a bug

Вопрос по API

Павел Делов 1 year ago updated by Андрей Ринас2 (ATAS developer) 1 year ago 2

Добрый день!

Пытаюсь разобраться в документации API, рассматриваю представленный пример стратегии SMA (API Strategies/ API Chart Strategies/ Samples/ Sample SMA strategy).

1) Код, который указан в примере, при копировании в Visual Studio не может идентифицировать конструкцию [Parameters]. Соответственно вопрос, какую библиотеку необходимо использовать для корректной работы этой конструкции?

2) После принудительной компиляции файла .dll со стратегией из примера, и при перемещении его в папку Strategies, ATAS либо зависает при попытке открытия этой стратегии, либо выдает ошибку:

Что в коде указано не корректно?

Все ссылки на библиотеки (ATAS.Indicators; ATAS.Indicators.Technical; ATAS.DataFeedsCore; ATAS.Strategies) взяты из ATAS версии 5.6.19.

Вот код, который сейчас использую и выдает вышеописанные ошибки (на 99% состоит из примера):

using System;

using System.ComponentModel.DataAnnotations;

using System.Windows.Media;

using ATAS.Indicators;

using ATAS.Indicators.Technical;

using ATAS.DataFeedsCore;

using Utils.Common.Logging;

using ParameterAttribute = Utils.Common.Attributes.ParameterAttribute;

namespace CustomStrategy

{

public class SmaChartStrategy : ATAS.Strategies.Chart.ChartStrategy

{

#region Private fields

private readonly SMA _shortSma = new SMA();

private readonly SMA _longSma = new SMA();

private int _lastBar;

#endregion

#region Public properties

[Display(

Name = "Short period",

Order = 10)]

[Parameter]

public int ShortPeriod

{

get => _shortSma.Period;

set

{

_shortSma.Period = Math.Max(1, value);

RecalculateValues();

}

}

[Display(

Name = "Long period",

Order = 20)]

[Parameter]

public int LongPeriod

{

get => _longSma.Period;

set

{

_longSma.Period = Math.Max(1, value);

RecalculateValues();

}

}

[Display(

Name = "Volume",

Order = 30)]

[Parameter]

public decimal Volume { get; set; }

[Display(ResourceType = typeof(Utils.Xaml.Properties.Resources),

Name = "ClosePositionOnStopping",

Order = 40)]

[Parameter]

public bool ClosePositionOnStopping { get; set; }

#endregion

#region ctor

public SmaChartStrategy()

{

var firstSeries = (ValueDataSeries)DataSeries[0];

firstSeries.Name = "Short";

firstSeries.Color = Colors.Red;

firstSeries.VisualType = VisualMode.Line;

DataSeries.Add(new ValueDataSeries("Long")

{

VisualType = VisualMode.Line,

Color = Colors.Green,

});

ShortPeriod = 21;

LongPeriod = 75;

Volume = 1;

ClosePositionOnStopping = true;

}

#endregion

#region Overrides of BaseIndicator

protected override void OnCalculate(int bar, decimal value)

{

var shortSma = _shortSma.Calculate(bar, value);

var longSma = _longSma.Calculate(bar, value);

DataSeries[0][bar] = shortSma;

DataSeries[1][bar] = longSma;

var prevBar = _lastBar;

_lastBar = bar;

if (!CanProcess(bar) || prevBar == bar)

return;

if (_shortSma[prevBar - 1] < _longSma[prevBar - 1] && _shortSma[prevBar] >= _longSma[prevBar])

{

//cross up

OpenPosition(OrderDirections.Buy);

}

if (_shortSma[prevBar - 1] > _longSma[prevBar - 1] && _shortSma[prevBar] <= _longSma[prevBar])

{

//cross down

OpenPosition(OrderDirections.Sell);

}

}

protected override void OnStopping()

{

if (CurrentPosition != 0 && ClosePositionOnStopping)

{

RaiseShowNotification($"Closing current position {CurrentPosition} on stopping.", level: LoggingLevel.Warning);

CloseCurrentPosition();

}

base.OnStopping();

}

#endregion

#region Private methods

private void OpenPosition(OrderDirections direction)

{

var order = new Order

{

Portfolio = Portfolio,

Security = Security,

Direction = direction,

Type = OrderTypes.Market,

QuantityToFill = GetOrderVolume(),

};

OpenOrder(order);

}

private void CloseCurrentPosition()

{

var order = new Order

{

Portfolio = Portfolio,

Security = Security,

Direction = CurrentPosition > 0 ? OrderDirections.Sell : OrderDirections.Buy,

Type = OrderTypes.Market,

QuantityToFill = Math.Abs(CurrentPosition),

};

OpenOrder(order);

}

private decimal GetOrderVolume()

{

if (CurrentPosition == 0)

return Volume;

if (CurrentPosition > 0)

return Volume + CurrentPosition;

return Volume + Math.Abs(CurrentPosition);

}

#endregion

}

}

" data-object-type="topic" data-object-id="33123" data-action="follow" data-original-title="Когда кто-то делает обновление здесь, Вы получите электронное письмо с деталями" style="box-sizing: border-box; margin: 0px; font-style: inherit; font-variant: inherit; font-weight: bold; font-stretch: inherit; font-size: 14px; line-height: 1.42857; font-family: inherit; color: rgb(255, 255, 255); overflow: visible; text-transform: none; -webkit-appearance: button; cursor: pointer; display: inline-block; padding: 6px 12px; text-align: center; white-space: nowrap; vertical-align: middle; user-select: none; background-image: none; border: 1px solid rgb(57, 132, 57); border-radius: 4px; background-color: rgb(68, 157, 68); float: right !important; outline: 0px; box-shadow: rgba(0, 0, 0, 0.125) 0px 3px 5px inset;"> Подписан


Скрин ошибки:

Not a bug

Высылаем исходники проекта с примером этой стратегии: https://atas.net/Setup/SampleStrategy.zip