diff --git a/core/models/side.py b/core/models/side.py index 5735d8a0..b2c4b911 100644 --- a/core/models/side.py +++ b/core/models/side.py @@ -8,6 +8,7 @@ class PositionSide(Enum): def __str__(self): return self.value + class SignalSide(Enum): BUY = "buy" SELL = "sell" diff --git a/quant.py b/quant.py index ac6bbbf2..5e823dc1 100644 --- a/quant.py +++ b/quant.py @@ -18,7 +18,7 @@ from optimization import StrategyOptimizerFactory from portfolio import Portfolio from position import PositionActorFactory, PositionFactory -from position.risk.volatility import PositionRiskVolatilityStrategy +from position.risk.break_even import PositionRiskBreakEvenStrategy from position.size.optimal_f import PositionOptimalFSizeStrategy from position.take_profit.risk_reward import PositionRiskRewardTakeProfitStrategy from risk import RiskActorFactory @@ -69,7 +69,7 @@ async def main(): position_factory = PositionFactory( PositionOptimalFSizeStrategy(), - PositionRiskVolatilityStrategy(config_service), + PositionRiskBreakEvenStrategy(config_service), PositionRiskRewardTakeProfitStrategy(config_service), ) diff --git a/strategy/generator/bootstrap/_trend_follow.py b/strategy/generator/bootstrap/_trend_follow.py index 2b0cbbd3..678c09ac 100644 --- a/strategy/generator/bootstrap/_trend_follow.py +++ b/strategy/generator/bootstrap/_trend_follow.py @@ -44,6 +44,8 @@ from strategy.generator.signal.dch_two_ma import Dch2MaSignal from strategy.generator.signal.di_cross import DiCrossSignal from strategy.generator.signal.dmi_cross import DmiCrossSignal +from strategy.generator.signal.dso_cross import DsoCrossSignal +from strategy.generator.signal.dso_flip import DsoFlipSignal from strategy.generator.signal.hl import HighLowSignal from strategy.generator.signal.kst_cross import KstCrossSignal from strategy.generator.signal.ma_three_cross import Ma3CrossSignal @@ -305,6 +307,7 @@ def _generate_signal(self, signal: TrendSignalType): return np.random.choice( [ AoFlipSignal(), + DsoFlipSignal(), MacdFlipSignal(), SupertrendFlipSignal(), RocFlipSignal(), @@ -356,6 +359,7 @@ def _generate_signal(self, signal: TrendSignalType): QstickCrossSignal(), VwapCrossSignal(), DmiCrossSignal(), + DsoCrossSignal(), StochCrossSignal(), KstCrossSignal(), TrixCrossSignal(), diff --git a/strategy/generator/signal/base.py b/strategy/generator/signal/base.py index 9dc9e2e9..4e7dcf49 100644 --- a/strategy/generator/signal/base.py +++ b/strategy/generator/signal/base.py @@ -15,6 +15,8 @@ class SignalType(Enum): DiFlip = "DiFlip" DiCross = "DiCross" DmiCross = "DmiCross" + DsoFlip = "DsoFlip" + DsoCross = "DsoCross" HighLow = "HighLow" Ma3Cross = "Ma3Cross" MaTestingGround = "MaTestingGround" diff --git a/strategy/generator/signal/dso_cross.py b/strategy/generator/signal/dso_cross.py new file mode 100644 index 00000000..21f08164 --- /dev/null +++ b/strategy/generator/signal/dso_cross.py @@ -0,0 +1,15 @@ +from dataclasses import dataclass + +from core.models.parameter import Parameter, StaticParameter +from core.models.smooth import Smooth + +from .base import Signal, SignalType + + +@dataclass(frozen=True) +class DsoCrossSignal(Signal): + type: Signal = SignalType.DsoCross + smooth_type: Parameter = StaticParameter(Smooth.EMA) + smooth_period: Parameter = StaticParameter(13.0) + k_period: Parameter = StaticParameter(8.0) + d_period: Parameter = StaticParameter(9.0) diff --git a/strategy/generator/signal/dso_flip.py b/strategy/generator/signal/dso_flip.py new file mode 100644 index 00000000..003dfad8 --- /dev/null +++ b/strategy/generator/signal/dso_flip.py @@ -0,0 +1,15 @@ +from dataclasses import dataclass + +from core.models.parameter import Parameter, StaticParameter +from core.models.smooth import Smooth + +from .base import Signal, SignalType + + +@dataclass(frozen=True) +class DsoFlipSignal(Signal): + type: Signal = SignalType.DsoFlip + smooth_type: Parameter = StaticParameter(Smooth.EMA) + smooth_period: Parameter = StaticParameter(13.0) + k_period: Parameter = StaticParameter(8.0) + d_period: Parameter = StaticParameter(9.0) diff --git a/ta_lib/strategies/base/src/constants.rs b/ta_lib/strategies/base/src/constants.rs new file mode 100644 index 00000000..62db500e --- /dev/null +++ b/ta_lib/strategies/base/src/constants.rs @@ -0,0 +1,2 @@ +pub const ZERO_LINE: f32 = 0.; +pub const NEUTRALITY_LINE: f32 = 50.; diff --git a/ta_lib/strategies/base/src/lib.rs b/ta_lib/strategies/base/src/lib.rs index cfebf02d..c0841936 100644 --- a/ta_lib/strategies/base/src/lib.rs +++ b/ta_lib/strategies/base/src/lib.rs @@ -1,5 +1,6 @@ extern crate alloc; +mod constants; mod ffi; mod model; mod price; @@ -7,6 +8,7 @@ mod strategy; mod traits; pub mod prelude { + pub use crate::constants::*; pub use crate::ffi::*; pub use crate::model::{OHLCVSeries, OHLCV}; pub use crate::price::*; diff --git a/ta_lib/strategies/confirm/src/dpo.rs b/ta_lib/strategies/confirm/src/dpo.rs index 8d4d2716..7b7c79e3 100644 --- a/ta_lib/strategies/confirm/src/dpo.rs +++ b/ta_lib/strategies/confirm/src/dpo.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use trend::dpo; -const DPO_FILTER: f32 = 0.; - pub struct DPOConfirm { smooth_type: Smooth, period: usize, @@ -26,6 +24,6 @@ impl Confirm for DPOConfirm { fn validate(&self, data: &OHLCVSeries) -> (Series, Series) { let dpo = dpo(&data.close, self.smooth_type, self.period); - (dpo.sgt(&DPO_FILTER), dpo.slt(&DPO_FILTER)) + (dpo.sgt(&ZERO_LINE), dpo.slt(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/confirm/src/eom.rs b/ta_lib/strategies/confirm/src/eom.rs index e94ae3f6..f0cd00ce 100644 --- a/ta_lib/strategies/confirm/src/eom.rs +++ b/ta_lib/strategies/confirm/src/eom.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use volume::eom; -const EOM_FILTER: f32 = 0.; - pub struct EOMConfirm { smooth_type: Smooth, period: usize, @@ -36,6 +34,6 @@ impl Confirm for EOMConfirm { self.divisor, ); - (eom.sgt(&EOM_FILTER), eom.slt(&EOM_FILTER)) + (eom.sgt(&ZERO_LINE), eom.slt(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/confirm/src/roc.rs b/ta_lib/strategies/confirm/src/roc.rs index afd288dd..aa460405 100644 --- a/ta_lib/strategies/confirm/src/roc.rs +++ b/ta_lib/strategies/confirm/src/roc.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::roc; -const ROC_FILTER: f32 = 0.; - pub struct ROCConfirm { period: usize, } @@ -24,6 +22,6 @@ impl Confirm for ROCConfirm { fn validate(&self, data: &OHLCVSeries) -> (Series, Series) { let roc = roc(&data.close, self.period); - (roc.sgt(&ROC_FILTER), roc.slt(&ROC_FILTER)) + (roc.sgt(&ZERO_LINE), roc.slt(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/pulse/src/vo.rs b/ta_lib/strategies/pulse/src/vo.rs index bec3b634..e12e037b 100644 --- a/ta_lib/strategies/pulse/src/vo.rs +++ b/ta_lib/strategies/pulse/src/vo.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use volume::vo; -const VO_ZERO_LINE: f32 = 0.0; - pub struct VoPulse { smooth_type: Smooth, fast_period: usize, @@ -33,6 +31,6 @@ impl Pulse for VoPulse { self.slow_period, ); - (vo.sgt(&VO_ZERO_LINE), vo.sgt(&VO_ZERO_LINE)) + (vo.sgt(&ZERO_LINE), vo.sgt(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/signal/src/ao_flip.rs b/ta_lib/strategies/signal/src/ao_flip.rs index 69f6a3ad..3efaf609 100644 --- a/ta_lib/strategies/signal/src/ao_flip.rs +++ b/ta_lib/strategies/signal/src/ao_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::ao; -const AO_ZERO: f32 = 0.0; - pub struct AOFlipSignal { fast_period: usize, slow_period: usize, @@ -28,8 +26,8 @@ impl Signal for AOFlipSignal { let prev_ao = ao.shift(2); ( - ao.cross_over(&AO_ZERO) & prev_ao.slt(&AO_ZERO), - ao.cross_under(&AO_ZERO) & prev_ao.sgt(&AO_ZERO), + ao.cross_over(&ZERO_LINE) & prev_ao.slt(&ZERO_LINE), + ao.cross_under(&ZERO_LINE) & prev_ao.sgt(&ZERO_LINE), ) } } diff --git a/ta_lib/strategies/signal/src/ao_saucer.rs b/ta_lib/strategies/signal/src/ao_saucer.rs index 3c724a12..704b3f8e 100644 --- a/ta_lib/strategies/signal/src/ao_saucer.rs +++ b/ta_lib/strategies/signal/src/ao_saucer.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::ao; -const AO_ZERO: f32 = 0.0; - pub struct AOSaucerSignal { fast_period: usize, slow_period: usize, @@ -31,17 +29,17 @@ impl Signal for AOSaucerSignal { let back_2_diff = diff.shift(2); ( - ao.sgt(&AO_ZERO) - & diff.sgt(&AO_ZERO) + ao.sgt(&ZERO_LINE) + & diff.sgt(&ZERO_LINE) & diff.sgt(&prev_diff) - & prev_diff.slt(&AO_ZERO) - & back_2_diff.slt(&AO_ZERO) + & prev_diff.slt(&ZERO_LINE) + & back_2_diff.slt(&ZERO_LINE) & prev_diff.slt(&back_2_diff), - ao.slt(&AO_ZERO) - & diff.slt(&AO_ZERO) + ao.slt(&ZERO_LINE) + & diff.slt(&ZERO_LINE) & diff.slt(&prev_diff) - & prev_diff.sgt(&AO_ZERO) - & back_2_diff.sgt(&AO_ZERO) + & prev_diff.sgt(&ZERO_LINE) + & back_2_diff.sgt(&ZERO_LINE) & prev_diff.slt(&back_2_diff), ) } diff --git a/ta_lib/strategies/signal/src/apo_flip.rs b/ta_lib/strategies/signal/src/apo_flip.rs index e5d62743..9dbc86ce 100644 --- a/ta_lib/strategies/signal/src/apo_flip.rs +++ b/ta_lib/strategies/signal/src/apo_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::apo; -const APO_ZERO: f32 = 0.0; - pub struct APOFlipSignal { fast_period: usize, slow_period: usize, @@ -26,6 +24,6 @@ impl Signal for APOFlipSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let apo = apo(&data.close, self.fast_period, self.slow_period); - (apo.cross_over(&APO_ZERO), apo.cross_under(&APO_ZERO)) + (apo.cross_over(&ZERO_LINE), apo.cross_under(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/signal/src/bop_flip.rs b/ta_lib/strategies/signal/src/bop_flip.rs index 2ba00183..0070f1ca 100644 --- a/ta_lib/strategies/signal/src/bop_flip.rs +++ b/ta_lib/strategies/signal/src/bop_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::bop; -const BOP_ZERO: f32 = 0.0; - pub struct BOPFlipSignal { smooth_type: Smooth, smooth_period: usize, @@ -33,6 +31,6 @@ impl Signal for BOPFlipSignal { self.smooth_period, ); - (bop.cross_over(&BOP_ZERO), bop.cross_under(&BOP_ZERO)) + (bop.cross_over(&ZERO_LINE), bop.cross_under(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/signal/src/cc_flip.rs b/ta_lib/strategies/signal/src/cc_flip.rs index d31cd50e..78c22fc4 100644 --- a/ta_lib/strategies/signal/src/cc_flip.rs +++ b/ta_lib/strategies/signal/src/cc_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::cc; -const ZERO_LINE: f32 = 0.0; - pub struct CCFlipSignal { fast_period: usize, slow_period: usize, diff --git a/ta_lib/strategies/signal/src/ce_flip.rs b/ta_lib/strategies/signal/src/ce_flip.rs index c8bc0cce..5bd3aedf 100644 --- a/ta_lib/strategies/signal/src/ce_flip.rs +++ b/ta_lib/strategies/signal/src/ce_flip.rs @@ -2,9 +2,6 @@ use base::prelude::*; use core::prelude::*; use trend::ce; -const ONE: f32 = 1.0; -const MINUS_ONE: f32 = -1.0; - pub struct CEFlipSignal { period: usize, atr_period: usize, diff --git a/ta_lib/strategies/signal/src/cfo_flip.rs b/ta_lib/strategies/signal/src/cfo_flip.rs index 6b1677f3..a4a57c40 100644 --- a/ta_lib/strategies/signal/src/cfo_flip.rs +++ b/ta_lib/strategies/signal/src/cfo_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::cfo; -const CFO_ZERO: f32 = 0.0; - pub struct CFOFlipSignal { period: usize, } @@ -24,6 +22,6 @@ impl Signal for CFOFlipSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let cfo = cfo(&data.close, self.period); - (cfo.cross_over(&CFO_ZERO), cfo.cross_under(&CFO_ZERO)) + (cfo.cross_over(&ZERO_LINE), cfo.cross_under(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/signal/src/di_flip.rs b/ta_lib/strategies/signal/src/di_flip.rs index 16de1d72..52db7634 100644 --- a/ta_lib/strategies/signal/src/di_flip.rs +++ b/ta_lib/strategies/signal/src/di_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::di; -const ZERO_LINE: f32 = 0.0; - pub struct DIFlipSignal { smooth_type: Smooth, period: usize, diff --git a/ta_lib/strategies/signal/src/dso_cross.rs b/ta_lib/strategies/signal/src/dso_cross.rs new file mode 100644 index 00000000..76ba4f02 --- /dev/null +++ b/ta_lib/strategies/signal/src/dso_cross.rs @@ -0,0 +1,40 @@ +use base::prelude::*; +use core::prelude::*; +use momentum::dso; + +pub struct DSOCrossSignal { + smooth_type: Smooth, + smooth_period: usize, + k_period: usize, + d_period: usize, +} + +impl DSOCrossSignal { + pub fn new(smooth_type: Smooth, smooth_period: f32, k_period: f32, d_period: f32) -> Self { + Self { + smooth_type, + smooth_period: smooth_period as usize, + k_period: k_period as usize, + d_period: d_period as usize, + } + } +} + +impl Signal for DSOCrossSignal { + fn lookback(&self) -> usize { + let period = std::cmp::max(self.smooth_period, self.k_period); + std::cmp::max(period, self.d_period) + } + + fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { + let (k, d) = dso( + &data.close, + self.smooth_type, + self.smooth_period, + self.k_period, + self.d_period, + ); + + (k.cross_over(&d), k.cross_under(&d)) + } +} diff --git a/ta_lib/strategies/signal/src/dso_flip.rs b/ta_lib/strategies/signal/src/dso_flip.rs new file mode 100644 index 00000000..2ea0a6de --- /dev/null +++ b/ta_lib/strategies/signal/src/dso_flip.rs @@ -0,0 +1,43 @@ +use base::prelude::*; +use core::prelude::*; +use momentum::dso; + +pub struct DSOFlipSignal { + smooth_type: Smooth, + smooth_period: usize, + k_period: usize, + d_period: usize, +} + +impl DSOFlipSignal { + pub fn new(smooth_type: Smooth, smooth_period: f32, k_period: f32, d_period: f32) -> Self { + Self { + smooth_type, + smooth_period: smooth_period as usize, + k_period: k_period as usize, + d_period: d_period as usize, + } + } +} + +impl Signal for DSOFlipSignal { + fn lookback(&self) -> usize { + let period = std::cmp::max(self.smooth_period, self.k_period); + std::cmp::max(period, self.d_period) + } + + fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { + let (k, _) = dso( + &data.close, + self.smooth_type, + self.smooth_period, + self.k_period, + self.d_period, + ); + + ( + k.cross_over(&NEUTRALITY_LINE), + k.cross_under(&NEUTRALITY_LINE), + ) + } +} diff --git a/ta_lib/strategies/signal/src/lib.rs b/ta_lib/strategies/signal/src/lib.rs index c896d8e9..bbf33255 100644 --- a/ta_lib/strategies/signal/src/lib.rs +++ b/ta_lib/strategies/signal/src/lib.rs @@ -9,6 +9,8 @@ mod dch_two_ma; mod di_cross; mod di_flip; mod dmi_cross; +mod dso_cross; +mod dso_flip; mod hl; mod kst_cross; mod ma_candle; @@ -58,6 +60,8 @@ pub use dch_two_ma::DCH2MASignal; pub use di_cross::DICrossSignal; pub use di_flip::DIFlipSignal; pub use dmi_cross::DMICrossSignal; +pub use dso_cross::DSOCrossSignal; +pub use dso_flip::DSOFlipSignal; pub use hl::HighLowSignal; pub use kst_cross::KSTCrossSignal; pub use ma_candle::MACandleSignal; diff --git a/ta_lib/strategies/signal/src/macd_color_switch.rs b/ta_lib/strategies/signal/src/macd_color_switch.rs index daa56563..1fafa46f 100644 --- a/ta_lib/strategies/signal/src/macd_color_switch.rs +++ b/ta_lib/strategies/signal/src/macd_color_switch.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::macd; -const ZERO_LINE: f32 = 0.0; - pub struct MACDColorSwitchSignal { smooth_type: Smooth, fast_period: usize, diff --git a/ta_lib/strategies/signal/src/macd_flip.rs b/ta_lib/strategies/signal/src/macd_flip.rs index aacdef30..abd7f7d3 100644 --- a/ta_lib/strategies/signal/src/macd_flip.rs +++ b/ta_lib/strategies/signal/src/macd_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::macd; -const ZERO_LINE: f32 = 0.0; - pub struct MACDFlipSignal { smooth_type: Smooth, fast_period: usize, diff --git a/ta_lib/strategies/signal/src/qstick_flip.rs b/ta_lib/strategies/signal/src/qstick_flip.rs index 73b1812c..305ca5a2 100644 --- a/ta_lib/strategies/signal/src/qstick_flip.rs +++ b/ta_lib/strategies/signal/src/qstick_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use trend::qstick; -const ZERO_LINE: f32 = 0.0; - pub struct QSTICKFlipSignal { smooth_type: Smooth, period: usize, diff --git a/ta_lib/strategies/signal/src/roc_flip.rs b/ta_lib/strategies/signal/src/roc_flip.rs index bec41ce9..2d6ebf9b 100644 --- a/ta_lib/strategies/signal/src/roc_flip.rs +++ b/ta_lib/strategies/signal/src/roc_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::roc; -const ROC_ZERO: f32 = 0.0; - pub struct ROCFlipSignal { period: usize, } @@ -24,6 +22,6 @@ impl Signal for ROCFlipSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let roc = roc(&data.close, self.period); - (roc.cross_over(&ROC_ZERO), roc.cross_under(&ROC_ZERO)) + (roc.cross_over(&ZERO_LINE), roc.cross_under(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/signal/src/rsi_ma_pullback.rs b/ta_lib/strategies/signal/src/rsi_ma_pullback.rs index a2ac71d3..3b82d8d7 100644 --- a/ta_lib/strategies/signal/src/rsi_ma_pullback.rs +++ b/ta_lib/strategies/signal/src/rsi_ma_pullback.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::rsi; -const RSI_NEUTRALITY: f32 = 50.0; - pub struct RSIMaPullbackSignal { smooth_type: Smooth, rsi_period: usize, @@ -38,8 +36,8 @@ impl Signal for RSIMaPullbackSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let rsi = rsi(&data.close, self.smooth_type, self.rsi_period); let rsi_ma = rsi.smooth(self.smooth_signal, self.smooth_period); - let upper_neutrality = RSI_NEUTRALITY + self.threshold; - let lower_neutrality = RSI_NEUTRALITY - self.threshold; + let upper_neutrality = NEUTRALITY_LINE + self.threshold; + let lower_neutrality = NEUTRALITY_LINE - self.threshold; let prev_rsi = rsi.shift(1); let back_2_rsi = rsi.shift(2); diff --git a/ta_lib/strategies/signal/src/rsi_neutrality_cross.rs b/ta_lib/strategies/signal/src/rsi_neutrality_cross.rs index db9796d9..5333ad40 100644 --- a/ta_lib/strategies/signal/src/rsi_neutrality_cross.rs +++ b/ta_lib/strategies/signal/src/rsi_neutrality_cross.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::rsi; -const RSI_NEUTRALITY: f32 = 50.0; - pub struct RSINeutralityCrossSignal { smooth_type: Smooth, rsi_period: usize, @@ -27,8 +25,8 @@ impl Signal for RSINeutralityCrossSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let rsi = rsi(&data.close, self.smooth_type, self.rsi_period); - let upper_neutrality = RSI_NEUTRALITY + self.threshold; - let lower_neutrality = RSI_NEUTRALITY - self.threshold; + let upper_neutrality = NEUTRALITY_LINE + self.threshold; + let lower_neutrality = NEUTRALITY_LINE - self.threshold; let prev_rsi = rsi.shift(1); let back_2_rsi = rsi.shift(2); @@ -37,15 +35,15 @@ impl Signal for RSINeutralityCrossSignal { ( rsi.sgt(&upper_neutrality) - & prev_rsi.sgt(&RSI_NEUTRALITY) - & back_2_rsi.slt(&RSI_NEUTRALITY) - & back_3_rsi.slt(&RSI_NEUTRALITY) - & back_4_rsi.slt(&RSI_NEUTRALITY), + & prev_rsi.sgt(&NEUTRALITY_LINE) + & back_2_rsi.slt(&NEUTRALITY_LINE) + & back_3_rsi.slt(&NEUTRALITY_LINE) + & back_4_rsi.slt(&NEUTRALITY_LINE), rsi.slt(&lower_neutrality) - & prev_rsi.slt(&RSI_NEUTRALITY) - & back_2_rsi.sgt(&RSI_NEUTRALITY) - & back_3_rsi.sgt(&RSI_NEUTRALITY) - & back_4_rsi.sgt(&RSI_NEUTRALITY), + & prev_rsi.slt(&NEUTRALITY_LINE) + & back_2_rsi.sgt(&NEUTRALITY_LINE) + & back_3_rsi.sgt(&NEUTRALITY_LINE) + & back_4_rsi.sgt(&NEUTRALITY_LINE), ) } } diff --git a/ta_lib/strategies/signal/src/rsi_neutrality_pullback.rs b/ta_lib/strategies/signal/src/rsi_neutrality_pullback.rs index dd4465bb..8be24076 100644 --- a/ta_lib/strategies/signal/src/rsi_neutrality_pullback.rs +++ b/ta_lib/strategies/signal/src/rsi_neutrality_pullback.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::rsi; -const RSI_NEUTRALITY: f32 = 50.0; - pub struct RSINeutralityPullbackSignal { smooth_type: Smooth, rsi_period: usize, @@ -27,24 +25,24 @@ impl Signal for RSINeutralityPullbackSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let rsi = rsi(&data.close, self.smooth_type, self.rsi_period); - let upper_neutrality = RSI_NEUTRALITY + self.threshold; - let lower_neutrality = RSI_NEUTRALITY - self.threshold; + let upper_neutrality = NEUTRALITY_LINE + self.threshold; + let lower_neutrality = NEUTRALITY_LINE - self.threshold; let prev_rsi = rsi.shift(1); let back_2_rsi = rsi.shift(2); let back_3_rsi = rsi.shift(3); ( - prev_rsi.sgt(&RSI_NEUTRALITY) + prev_rsi.sgt(&NEUTRALITY_LINE) & prev_rsi.slt(&lower_neutrality) & prev_rsi.slt(&back_2_rsi) - & back_2_rsi.sgt(&RSI_NEUTRALITY) - & back_3_rsi.slt(&RSI_NEUTRALITY), - prev_rsi.slt(&RSI_NEUTRALITY) + & back_2_rsi.sgt(&NEUTRALITY_LINE) + & back_3_rsi.slt(&NEUTRALITY_LINE), + prev_rsi.slt(&NEUTRALITY_LINE) & prev_rsi.sgt(&upper_neutrality) & prev_rsi.sgt(&back_2_rsi) - & back_2_rsi.slt(&RSI_NEUTRALITY) - & back_3_rsi.sgt(&RSI_NEUTRALITY), + & back_2_rsi.slt(&NEUTRALITY_LINE) + & back_3_rsi.sgt(&NEUTRALITY_LINE), ) } } diff --git a/ta_lib/strategies/signal/src/rsi_neutrality_rejection.rs b/ta_lib/strategies/signal/src/rsi_neutrality_rejection.rs index 9989f4d5..a385162a 100644 --- a/ta_lib/strategies/signal/src/rsi_neutrality_rejection.rs +++ b/ta_lib/strategies/signal/src/rsi_neutrality_rejection.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::rsi; -const RSI_NEUTRALITY: f32 = 50.0; - pub struct RSINeutralityRejectionSignal { smooth_type: Smooth, rsi_period: usize, @@ -27,8 +25,8 @@ impl Signal for RSINeutralityRejectionSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let rsi = rsi(&data.close, self.smooth_type, self.rsi_period); - let upper_neutrality = RSI_NEUTRALITY + self.threshold; - let lower_neutrality = RSI_NEUTRALITY - self.threshold; + let upper_neutrality = NEUTRALITY_LINE + self.threshold; + let lower_neutrality = NEUTRALITY_LINE - self.threshold; let prev_rsi = rsi.shift(1); let back_2_rsi = rsi.shift(2); @@ -36,13 +34,13 @@ impl Signal for RSINeutralityRejectionSignal { ( rsi.sgt(&upper_neutrality) - & prev_rsi.slt(&RSI_NEUTRALITY) - & back_2_rsi.sgt(&RSI_NEUTRALITY) - & back_3_rsi.sgt(&RSI_NEUTRALITY), + & prev_rsi.slt(&NEUTRALITY_LINE) + & back_2_rsi.sgt(&NEUTRALITY_LINE) + & back_3_rsi.sgt(&NEUTRALITY_LINE), rsi.slt(&lower_neutrality) - & prev_rsi.sgt(&RSI_NEUTRALITY) - & back_2_rsi.slt(&RSI_NEUTRALITY) - & back_3_rsi.slt(&RSI_NEUTRALITY), + & prev_rsi.sgt(&NEUTRALITY_LINE) + & back_2_rsi.slt(&NEUTRALITY_LINE) + & back_3_rsi.slt(&NEUTRALITY_LINE), ) } } diff --git a/ta_lib/strategies/signal/src/rsi_supertrend.rs b/ta_lib/strategies/signal/src/rsi_supertrend.rs index 1f4a4dd1..0e710fe3 100644 --- a/ta_lib/strategies/signal/src/rsi_supertrend.rs +++ b/ta_lib/strategies/signal/src/rsi_supertrend.rs @@ -5,7 +5,6 @@ use trend::supertrend; const RSI_UPPER_BARRIER: f32 = 75.0; const RSI_LOWER_BARRIER: f32 = 25.0; -const RSI_NEUTRALITY: f32 = 50.0; pub struct RSISupertrendSignal { smooth_type: Smooth, @@ -48,8 +47,8 @@ impl Signal for RSISupertrendSignal { ); let lower_barrier = RSI_LOWER_BARRIER + self.threshold; let upper_barrier = RSI_UPPER_BARRIER - self.threshold; - let lower_neutrality = RSI_NEUTRALITY - self.threshold; - let upper_neutrality = RSI_NEUTRALITY + self.threshold; + let lower_neutrality = NEUTRALITY_LINE - self.threshold; + let upper_neutrality = NEUTRALITY_LINE + self.threshold; let prev_direction = direction.shift(1); let back_2_direction = direction.shift(2); @@ -64,7 +63,7 @@ impl Signal for RSISupertrendSignal { & prev_direction.seq(&ONE) & back_2_direction.seq(&ONE) & back_3_direction.seq(&ONE) - & rsi.sgt(&RSI_NEUTRALITY) + & rsi.sgt(&NEUTRALITY_LINE) & rsi.slt(&upper_barrier) & prev_rsi.sgt(&lower_neutrality) & back_2_rsi.sgt(&lower_neutrality) @@ -73,7 +72,7 @@ impl Signal for RSISupertrendSignal { & prev_direction.seq(&MINUS_ONE) & back_2_direction.seq(&MINUS_ONE) & back_3_direction.seq(&MINUS_ONE) - & rsi.slt(&RSI_NEUTRALITY) + & rsi.slt(&NEUTRALITY_LINE) & rsi.sgt(&lower_barrier) & prev_rsi.slt(&upper_neutrality) & back_2_rsi.slt(&upper_neutrality) diff --git a/ta_lib/strategies/signal/src/trix_flip.rs b/ta_lib/strategies/signal/src/trix_flip.rs index f21a0258..4a018568 100644 --- a/ta_lib/strategies/signal/src/trix_flip.rs +++ b/ta_lib/strategies/signal/src/trix_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::trix; -const TRIX_ZERO: f32 = 0.0; - pub struct TRIXFlipSignal { smooth_type: Smooth, period: usize, @@ -26,6 +24,6 @@ impl Signal for TRIXFlipSignal { fn generate(&self, data: &OHLCVSeries) -> (Series, Series) { let trix = trix(&data.close, self.smooth_type, self.period); - (trix.cross_over(&TRIX_ZERO), trix.cross_under(&TRIX_ZERO)) + (trix.cross_over(&ZERO_LINE), trix.cross_under(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/signal/src/tsi_flip.rs b/ta_lib/strategies/signal/src/tsi_flip.rs index 51bc9b0a..3d8f7cd1 100644 --- a/ta_lib/strategies/signal/src/tsi_flip.rs +++ b/ta_lib/strategies/signal/src/tsi_flip.rs @@ -2,8 +2,6 @@ use base::prelude::*; use core::prelude::*; use momentum::tsi; -const TSI_ZERO_LINE: f32 = 0.0; - pub struct TSIFlipSignal { smooth_type: Smooth, fast_period: usize, @@ -33,9 +31,6 @@ impl Signal for TSIFlipSignal { self.fast_period, ); - ( - tsi.cross_over(&TSI_ZERO_LINE), - tsi.cross_under(&TSI_ZERO_LINE), - ) + (tsi.cross_over(&ZERO_LINE), tsi.cross_under(&ZERO_LINE)) } } diff --git a/ta_lib/strategies/trend_follow/src/signal_mapper.rs b/ta_lib/strategies/trend_follow/src/signal_mapper.rs index 210ab719..f9ad7fc3 100644 --- a/ta_lib/strategies/trend_follow/src/signal_mapper.rs +++ b/ta_lib/strategies/trend_follow/src/signal_mapper.rs @@ -43,6 +43,18 @@ pub enum SignalConfig { adx_period: f32, di_period: f32, }, + DsoFlip { + smooth_type: f32, + smooth_period: f32, + k_period: f32, + d_period: f32, + }, + DsoCross { + smooth_type: f32, + smooth_period: f32, + k_period: f32, + d_period: f32, + }, HighLow { period: f32, }, @@ -429,6 +441,28 @@ pub fn map_to_signal(config: SignalConfig) -> Box { map_to_smooth(smooth_type as usize), period, )), + SignalConfig::DsoFlip { + smooth_type, + smooth_period, + k_period, + d_period, + } => Box::new(DSOFlipSignal::new( + map_to_smooth(smooth_type as usize), + smooth_period, + k_period, + d_period, + )), + SignalConfig::DsoCross { + smooth_type, + smooth_period, + k_period, + d_period, + } => Box::new(DSOCrossSignal::new( + map_to_smooth(smooth_type as usize), + smooth_period, + k_period, + d_period, + )), SignalConfig::DiCross { smooth_type, period,