forked from tslab-hub/handlers
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathTradeStatisticsEdgeHandler.cs
More file actions
127 lines (102 loc) · 5.51 KB
/
TradeStatisticsEdgeHandler.cs
File metadata and controls
127 lines (102 loc) · 5.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using TSLab.Script.Handlers.Options;
namespace TSLab.Script.Handlers
{
// Не стоит навешивать на абстрактные классы атрибуты категорий и описания входов/выходов. Это снижает гибкость управления в перспективе.
public abstract class TradeStatisticsEdgeHandler : ITradeStatisticsEdgeHandler
{
public string VariableId { get; set; }
public IContext Context { get; set; }
/// <summary>
/// \~english Trim level (as percents).
/// \~russian Позволяет установить значение отсечки в процентах.
/// </summary>
[HelperName("Trim level, %", Constants.En)]
[HelperName("Уровень отсечки, %", Constants.Ru)]
[Description("Позволяет установить значение отсечки в процентах.")]
[HelperDescription("Trim level (as percents).", Constants.En)]
[HandlerParameter(true, "0", Min = "0", Max = "100", Step = "1", EditorMin = "0", EditorMax = "100")]
public double TrimLevelPercent { get; set; }
public IList<double> Execute(IBaseTradeStatisticsWithKind tradeStatistics)
{
var histograms = tradeStatistics.GetHistograms();
var tradeHistogramsCache = tradeStatistics.TradeHistogramsCache;
var barsCount = tradeHistogramsCache.Bars.Count;
var trimLevelPercent = TrimLevelPercent;
const double DefaultValue = double.NaN;
if (histograms.Count == 0 || histograms.All(item => item.Bars.Count == 0) || trimLevelPercent < 0 || trimLevelPercent > 100 || double.IsNaN(trimLevelPercent))
return new ConstGenBase<double>(barsCount, DefaultValue);
double[] results = null;
var runtime = Context?.Runtime;
var canBeCached = tradeStatistics.HasStaticTimeline && barsCount > 1 && runtime != null;
string id = null, stateId = null;
DerivativeTradeStatisticsCacheContext context = null;
var cachedCount = 0;
var lastResult = DefaultValue;
if (canBeCached)
{
id = string.Join(".", runtime.TradeName, runtime.IsAgentMode, VariableId);
stateId = TrimLevelPercent + "." + tradeStatistics.StateId;
context = DerivativeTradeStatisticsCache.Instance.GetContext(id, stateId, tradeHistogramsCache);
if (context != null)
{
var cachedResults = context.Values;
cachedCount = Math.Min(cachedResults.Length, barsCount) - 1;
if (cachedResults.Length == barsCount)
results = cachedResults;
else
Buffer.BlockCopy(cachedResults, 0, results = new double[barsCount], 0, cachedCount * sizeof(double));
lastResult = results[cachedCount - 1];
}
else
results = new double[barsCount];
}
else
results = Context?.GetArray<double>(barsCount) ?? new double[barsCount];
tradeStatistics.GetHistogramsBarIndexes(out var firstBarIndex, out var lastBarIndex);
for (var i = cachedCount; i < firstBarIndex; i++)
results[i] = lastResult;
lock (tradeStatistics.Source)
for (var i = Math.Max(cachedCount, firstBarIndex); i <= lastBarIndex; i++)
results[i] = lastResult = GetPrice(tradeStatistics, i, lastResult);
for (var i = Math.Max(cachedCount, lastBarIndex + 1); i < barsCount; i++)
results[i] = lastResult;
if (canBeCached)
DerivativeTradeStatisticsCache.Instance.SetContext(id, stateId, tradeHistogramsCache, results, context);
return results;
}
private double GetPrice(IBaseTradeStatisticsWithKind tradeStatistics, int barIndex, double lastPrice)
{
var bars = tradeStatistics.GetAggregatedHistogramBars(barIndex);
if (bars.Count == 0)
return lastPrice;
var allValuesSum = bars.Sum(item => Math.Abs(tradeStatistics.GetValue(item)));
if (allValuesSum == 0)
return lastPrice;
var trimLevelPercent = TrimLevelPercent;
if (trimLevelPercent == 0)
return GetFirstPrice(bars);
if (trimLevelPercent == 100)
return GetLastPrice(bars);
var edgeValuesSum = allValuesSum * trimLevelPercent / 100;
foreach (var bar in GetOrderedBars(bars))
{
var value = Math.Abs(tradeStatistics.GetValue(bar));
if (edgeValuesSum <= value)
{
var result = GetPrice(bar, edgeValuesSum / value);
return result;
}
edgeValuesSum -= value;
}
return GetLastPrice(bars);
}
protected abstract double GetFirstPrice(IReadOnlyList<ITradeHistogramBar> bars);
protected abstract double GetLastPrice(IReadOnlyList<ITradeHistogramBar> bars);
protected abstract IEnumerable<ITradeHistogramBar> GetOrderedBars(IEnumerable<ITradeHistogramBar> bar);
protected abstract double GetPrice(ITradeHistogramBar bar, double coefficient);
}
}