* Add synthApi * Put confidence for Synth proba * Update the code * Update readme * Fix bootstraping * fix github build * Update the endpoints for scenario * Add scenario and update backtest modal * Update bot modal * Update interfaces for synth * add synth to backtest * Add Kelly criterion and better signal * Update signal confidence * update doc * save leaderboard and prediction * Update nswag to generate ApiClient in the correct path * Unify the trading modal * Save miner and prediction * Update messaging and block new signal until position not close when flipping off * Rename strategies to indicators * Update doc * Update chart + add signal name * Fix signal direction * Update docker webui * remove crypto npm * Clean
125 lines
3.7 KiB
C#
125 lines
3.7 KiB
C#
using Managing.Core;
|
|
using Managing.Domain.Candles;
|
|
using Managing.Domain.Shared.Rules;
|
|
using Managing.Domain.Strategies.Base;
|
|
using Skender.Stock.Indicators;
|
|
using static Managing.Common.Enums;
|
|
|
|
namespace Managing.Domain.Strategies.Signals;
|
|
|
|
public class StcIndicator : Indicator
|
|
{
|
|
public List<Signal> Signals { get; set; }
|
|
|
|
public StcIndicator(string name, int cyclePeriods, int fastPeriods, int slowPeriods) : base(name, IndicatorType.Stc)
|
|
{
|
|
Signals = new List<Signal>();
|
|
FastPeriods = fastPeriods;
|
|
SlowPeriods = slowPeriods;
|
|
CyclePeriods = cyclePeriods;
|
|
}
|
|
|
|
public override List<Signal> Run()
|
|
{
|
|
if (Candles.Count <= 2 * (SlowPeriods + CyclePeriods))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
try
|
|
{
|
|
if (FastPeriods != null)
|
|
{
|
|
var stc = Candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList();
|
|
if (CyclePeriods != null)
|
|
{
|
|
var stcCandles = MapStcToCandle(stc, Candles.TakeLast(CyclePeriods.Value));
|
|
|
|
if (stc.Count == 0)
|
|
return null;
|
|
|
|
var previousCandle = stcCandles[0];
|
|
foreach (var currentCandle in stcCandles.Skip(1))
|
|
{
|
|
if (previousCandle.Stc > 75 && currentCandle.Stc <= 75)
|
|
{
|
|
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
|
|
}
|
|
|
|
if (previousCandle.Stc < 25 && currentCandle.Stc >= 25)
|
|
{
|
|
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
|
|
}
|
|
|
|
previousCandle = currentCandle;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Signals.Where(s => s.Confidence != Confidence.None).OrderBy(s => s.Date).ToList();
|
|
}
|
|
catch (RuleException)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public override IndicatorsResultBase GetIndicatorValues()
|
|
{
|
|
if (FastPeriods != null && SlowPeriods != null)
|
|
{
|
|
var stc = Candles.GetStc(FastPeriods.Value, FastPeriods.Value, SlowPeriods.Value).ToList();
|
|
return new IndicatorsResultBase
|
|
{
|
|
Stc = stc
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private List<CandleSct> MapStcToCandle(List<StcResult> stc, IEnumerable<Candle> candles)
|
|
{
|
|
var sctList = new List<CandleSct>();
|
|
foreach (var candle in candles)
|
|
{
|
|
var currentSct = stc.Find(candle.Date);
|
|
if (currentSct != null)
|
|
{
|
|
sctList.Add(new CandleSct()
|
|
{
|
|
Close = candle.Close,
|
|
Open = candle.Open,
|
|
Date = candle.Date,
|
|
Ticker = candle.Ticker,
|
|
Exchange = candle.Exchange,
|
|
Stc = currentSct.Stc
|
|
});
|
|
}
|
|
}
|
|
|
|
return sctList;
|
|
}
|
|
|
|
private void AddSignal(CandleSct candleSignal, TradeDirection direction, Confidence confidence)
|
|
{
|
|
var signal = new Signal(
|
|
MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker),
|
|
direction,
|
|
confidence,
|
|
candleSignal,
|
|
candleSignal.Date,
|
|
candleSignal.Exchange,
|
|
Type, SignalType,
|
|
Name);
|
|
if (!Signals.Any(s => s.Identifier == signal.Identifier))
|
|
{
|
|
Signals.AddItem(signal);
|
|
}
|
|
}
|
|
|
|
private class CandleSct : Candle
|
|
{
|
|
public double? Stc { get; internal set; }
|
|
}
|
|
} |