Skip to content

Commit 8b751cd

Browse files
committed
Strategy. Bind is decimal?
1 parent e22a8ca commit 8b751cd

7 files changed

Lines changed: 52 additions & 35 deletions

File tree

Algo/Strategies/Strategy_HighLevel.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public interface ISubscriptionHandler<T>
3636
/// <param name="indicator">Indicator.</param>
3737
/// <param name="callback">Callback.</param>
3838
/// <returns><see cref="ISubscriptionHandler{T}"/></returns>
39-
ISubscriptionHandler<T> Bind(IIndicator indicator, Action<T, decimal> callback);
39+
ISubscriptionHandler<T> Bind(IIndicator indicator, Action<T, decimal?> callback);
4040

4141
/// <summary>
4242
/// Bind indicator to the subscription.
@@ -53,7 +53,7 @@ public interface ISubscriptionHandler<T>
5353
/// <param name="indicator2">Indicator.</param>
5454
/// <param name="callback">Callback.</param>
5555
/// <returns><see cref="ISubscriptionHandler{T}"/></returns>
56-
ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, Action<T, decimal, decimal> callback);
56+
ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, Action<T, decimal?, decimal?> callback);
5757

5858
/// <summary>
5959
/// Bind indicators to the subscription.
@@ -72,7 +72,7 @@ public interface ISubscriptionHandler<T>
7272
/// <param name="indicator3">Indicator.</param>
7373
/// <param name="callback">Callback.</param>
7474
/// <returns><see cref="ISubscriptionHandler{T}"/></returns>
75-
ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, Action<T, decimal, decimal, decimal> callback);
75+
ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, Action<T, decimal?, decimal?, decimal?> callback);
7676

7777
/// <summary>
7878
/// Bind indicators to the subscription.
@@ -93,7 +93,7 @@ public interface ISubscriptionHandler<T>
9393
/// <param name="indicator4">Indicator.</param>
9494
/// <param name="callback">Callback.</param>
9595
/// <returns><see cref="ISubscriptionHandler{T}"/></returns>
96-
ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, IIndicator indicator4, Action<T, decimal, decimal, decimal, decimal> callback);
96+
ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, IIndicator indicator4, Action<T, decimal?, decimal?, decimal?, decimal?> callback);
9797

9898
/// <summary>
9999
/// Bind indicators to the subscription.
@@ -112,7 +112,7 @@ public interface ISubscriptionHandler<T>
112112
/// <param name="indicators">Indicators.</param>
113113
/// <param name="callback">Callback.</param>
114114
/// <returns><see cref="ISubscriptionHandler{T}"/></returns>
115-
ISubscriptionHandler<T> Bind(IIndicator[] indicators, Action<T, decimal[]> callback);
115+
ISubscriptionHandler<T> Bind(IIndicator[] indicators, Action<T, decimal?[]> callback);
116116

117117
/// <summary>
118118
/// Bind indicators to the subscription.
@@ -478,49 +478,49 @@ public ISubscriptionHandler<T> Bind(Action<T> callback)
478478
return this;
479479
}
480480

481-
public ISubscriptionHandler<T> Bind(IIndicator indicator, Action<T, decimal> callback)
481+
public ISubscriptionHandler<T> Bind(IIndicator indicator, Action<T, decimal?> callback)
482482
{
483483
if (callback is null)
484484
throw new ArgumentNullException(nameof(callback));
485485

486-
return BindEx(indicator, (v, iv) => callback(v, iv.ToDecimal()));
486+
return BindEx(indicator, (v, iv) => callback(v, iv.ToNullableDecimal()));
487487
}
488488

489-
public ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, Action<T, decimal, decimal> callback)
489+
public ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, Action<T, decimal?, decimal?> callback)
490490
{
491491
if (callback is null)
492492
throw new ArgumentNullException(nameof(callback));
493493

494-
return BindEx(indicator1, indicator2, (v, iv1, iv2) => callback(v, iv1.ToDecimal(), iv2.ToDecimal()));
494+
return BindEx(indicator1, indicator2, (v, iv1, iv2) => callback(v, iv1.ToNullableDecimal(), iv2.ToNullableDecimal()));
495495
}
496496

497-
public ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, Action<T, decimal, decimal, decimal> callback)
497+
public ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, Action<T, decimal?, decimal?, decimal?> callback)
498498
{
499499
if (callback is null)
500500
throw new ArgumentNullException(nameof(callback));
501501

502-
return BindEx(indicator1, indicator2, indicator3, (v, iv1, iv2, iv3) => callback(v, iv1.ToDecimal(), iv2.ToDecimal(), iv3.ToDecimal()));
502+
return BindEx(indicator1, indicator2, indicator3, (v, iv1, iv2, iv3) => callback(v, iv1.ToNullableDecimal(), iv2.ToNullableDecimal(), iv3.ToNullableDecimal()));
503503
}
504504

505-
public ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, IIndicator indicator4, Action<T, decimal, decimal, decimal, decimal> callback)
505+
public ISubscriptionHandler<T> Bind(IIndicator indicator1, IIndicator indicator2, IIndicator indicator3, IIndicator indicator4, Action<T, decimal?, decimal?, decimal?, decimal?> callback)
506506
{
507507
if (callback is null)
508508
throw new ArgumentNullException(nameof(callback));
509509

510510
return BindEx(indicator1, indicator2, indicator3, indicator4, (v, iv1, iv2, iv3, iv4) => callback(v, iv1.ToDecimal(), iv2.ToDecimal(), iv3.ToDecimal(), iv4.ToDecimal()));
511511
}
512512

513-
public ISubscriptionHandler<T> Bind(IIndicator[] indicators, Action<T, decimal[]> callback)
513+
public ISubscriptionHandler<T> Bind(IIndicator[] indicators, Action<T, decimal?[]> callback)
514514
{
515515
if (callback is null)
516516
throw new ArgumentNullException(nameof(callback));
517517

518518
return BindEx(indicators, (v, ivs) =>
519519
{
520-
var decimals = new decimal[ivs.Length];
520+
var decimals = new decimal?[ivs.Length];
521521

522522
for (var i = 0; i < ivs.Length; i++)
523-
decimals[i] = ivs[i].ToDecimal();
523+
decimals[i] = ivs[i].ToNullableDecimal();
524524

525525
callback(v, decimals);
526526
});

BusinessEntities/Indicators/IndicatorHelper.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,19 @@ public static decimal ToDecimal(this IIndicatorValue value)
289289
return value.GetValue<decimal>();
290290
}
291291

292+
/// <summary>
293+
/// Convert <see cref="IIndicatorValue"/> to <see cref="decimal"/> or <see langword="null"/> if the value is empty..
294+
/// </summary>
295+
/// <param name="value"><see cref="IIndicatorValue"/></param>
296+
/// <returns><see cref="decimal"/> or <see langword="null"/> if the value is empty.</returns>
297+
public static decimal? ToNullableDecimal(this IIndicatorValue value)
298+
{
299+
if (value is null)
300+
throw new ArgumentNullException(nameof(value));
301+
302+
return value.IsEmpty ? null : value.ToDecimal();
303+
}
304+
292305
/// <summary>
293306
/// Convert <see cref="IIndicatorValue"/> to <see cref="ICandleMessage"/>.
294307
/// </summary>

Designer.Templates/Backtest/SmaStrategy.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,12 @@ protected override void OnStarted(DateTimeOffset time)
136136
// ----------------------------------------
137137
}
138138

139-
private void OnProcess(ICandleMessage candle, decimal longValue, decimal shortValue)
139+
private void OnProcess(ICandleMessage candle, decimal? longValue, decimal? shortValue)
140140
{
141141
LogInfo(LocalizedStrings.SmaNewCandleLog, candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice, candle.TotalVolume, candle.SecurityId);
142142

143143
// in case we subscribed on non finished only candles
144-
if (candle.State != CandleStates.Finished)
144+
if (candle.State != CandleStates.Finished || shortValue is null || longValue is null)
145145
return;
146146

147147
// calc new values for short and long

Designer.Templates/Backtest/SmaStrategy.fs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ type SmaStrategy() as this =
143143
member private this.OnProcess
144144
(
145145
candle: ICandleMessage,
146-
longValue: decimal,
147-
shortValue: decimal
146+
longValue: Nullable<decimal>,
147+
shortValue: Nullable<decimal>
148148
) =
149149
// Log candle information
150150
this.LogInfo(
@@ -163,7 +163,11 @@ type SmaStrategy() as this =
163163
()
164164
else
165165
// Determine if short SMA is less than long SMA
166-
let shortLess = shortValue < longValue
166+
let shortLess =
167+
if shortValue.HasValue && longValue.HasValue then
168+
shortValue.Value < longValue.Value
169+
else
170+
false
167171

168172
match isShortLessThenLong with
169173
| None ->

Samples/06_Strategies/01_HistorySMA/SmaStrategyClassicStrategy.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ protected override void OnStarted(DateTimeOffset time)
8989
}
9090
}
9191

92-
private void ProcessCandle(ICandleMessage candle, decimal longValue, decimal shortValue)
92+
private void ProcessCandle(ICandleMessage candle, decimal? longValue, decimal? shortValue)
9393
{
9494
// Skip unfinished candles
95-
if (candle.State != CandleStates.Finished)
95+
if (candle.State != CandleStates.Finished || shortValue is null || longValue is null)
9696
return;
9797

9898
// Check if strategy is ready to trade
@@ -102,8 +102,8 @@ private void ProcessCandle(ICandleMessage candle, decimal longValue, decimal sho
102102
// For the first value, we just store it and don't generate signals
103103
if (_isFirstValue)
104104
{
105-
_prevLongValue = longValue;
106-
_prevShortValue = shortValue;
105+
_prevLongValue = longValue.Value;
106+
_prevShortValue = shortValue.Value;
107107
_isFirstValue = false;
108108
return;
109109
}
@@ -113,8 +113,8 @@ private void ProcessCandle(ICandleMessage candle, decimal longValue, decimal sho
113113
var isShortLessPrev = _prevShortValue < _prevLongValue;
114114

115115
// Store current values as previous for next candle
116-
_prevLongValue = longValue;
117-
_prevShortValue = shortValue;
116+
_prevLongValue = longValue.Value;
117+
_prevShortValue = shortValue.Value;
118118

119119
// Check for crossover (signal)
120120
if (isShortLessCurrent == isShortLessPrev)

Samples/06_Strategies/01_HistorySMA/SmaStrategyMartingaleStrategy.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ protected override void OnStarted(DateTimeOffset time)
9090
}
9191
}
9292

93-
private void ProcessCandle(ICandleMessage candle, decimal longValue, decimal shortValue)
93+
private void ProcessCandle(ICandleMessage candle, decimal? longValue, decimal? shortValue)
9494
{
9595
// Skip unfinished candles
96-
if (candle.State != CandleStates.Finished)
96+
if (candle.State != CandleStates.Finished || shortValue is null || longValue is null)
9797
return;
9898

9999
// Check if strategy is ready to trade
@@ -103,8 +103,8 @@ private void ProcessCandle(ICandleMessage candle, decimal longValue, decimal sho
103103
// For the first value, we just store it and don't generate signals
104104
if (_isFirstValue)
105105
{
106-
_prevLongValue = longValue;
107-
_prevShortValue = shortValue;
106+
_prevLongValue = longValue.Value;
107+
_prevShortValue = shortValue.Value;
108108
_isFirstValue = false;
109109
return;
110110
}
@@ -114,8 +114,8 @@ private void ProcessCandle(ICandleMessage candle, decimal longValue, decimal sho
114114
var isShortLessThenLongPrevious = _prevShortValue < _prevLongValue;
115115

116116
// Store current values as previous for next candle
117-
_prevLongValue = longValue;
118-
_prevShortValue = shortValue;
117+
_prevLongValue = longValue.Value;
118+
_prevShortValue = shortValue.Value;
119119

120120
// Check for crossover (signal)
121121
if (isShortLessThenLongPrevious == isShortLessThenLongCurrent)
@@ -131,7 +131,7 @@ private void ProcessCandle(ICandleMessage candle, decimal longValue, decimal sho
131131
var volume = Volume + Math.Abs(Position);
132132

133133
// Create and register the order with appropriate price
134-
var price = Security.ShrinkPrice(shortValue);
134+
var price = Security.ShrinkPrice(shortValue.Value);
135135
RegisterOrder(CreateOrder(direction, price, volume));
136136
}
137137
}

Samples/07_Testing/01_History/SmaStrategy.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,12 @@ protected override void OnStarted(DateTimeOffset time)
164164
// ----------------------------------------
165165
}
166166

167-
private void OnProcess(ICandleMessage candle, decimal longValue, decimal shortValue)
167+
private void OnProcess(ICandleMessage candle, decimal? longValue, decimal? shortValue)
168168
{
169169
LogInfo(LocalizedStrings.SmaNewCandleLog, candle.OpenTime, candle.OpenPrice, candle.HighPrice, candle.LowPrice, candle.ClosePrice, candle.TotalVolume, candle.SecurityId);
170170

171171
// in case we subscribed on non finished only candles
172-
if (candle.State != CandleStates.Finished)
172+
if (candle.State != CandleStates.Finished || shortValue is null || longValue is null)
173173
return;
174174

175175
// calc new values for short and long

0 commit comments

Comments
 (0)