Add StochasticCross indicator support in CustomScenario and TradeChart components

- Implemented StochasticCross indicator in CustomScenario with associated parameters and labels.
- Enhanced TradeChart to visualize StochasticCross data, including %K and %D series.
- Updated API and types to include kFactor and dFactor properties for StochasticCross.
- Modified backtest and scenario pages to incorporate StochasticCross in indicator lists and parameter mappings.
This commit is contained in:
2025-11-24 11:04:05 +07:00
parent 43d7c5c929
commit 18f868a221
9 changed files with 685 additions and 15 deletions

View File

@@ -53,7 +53,11 @@ const CustomScenario: React.FC<ICustomScenario> = ({
case IndicatorType.StochRsiTrend:
params = ['period', 'stochPeriods', 'signalPeriods', 'smoothPeriods'];
break;
case IndicatorType.StochasticCross:
params = ['stochPeriods', 'signalPeriods', 'smoothPeriods', 'kFactor', 'dFactor'];
break;
case IndicatorType.Stc:
case IndicatorType.LaggingStc:
params = ['cyclePeriods', 'fastPeriods', 'slowPeriods'];
@@ -97,6 +101,9 @@ const CustomScenario: React.FC<ICustomScenario> = ({
case IndicatorType.StochRsiTrend:
label = 'Stoch RSI Trend';
break;
case IndicatorType.StochasticCross:
label = 'Stochastic Cross';
break;
case IndicatorType.Stc:
label = 'STC';
break;

View File

@@ -18,7 +18,6 @@ import type {
Candle,
IndicatorsResultBase,
IndicatorType,
KeyValuePairOfDateTimeAndDecimal,
LightSignal,
Position,
} from '../../../../generated/ManagingApi'
@@ -44,8 +43,8 @@ type ITradeChartProps = {
candles: Candle[]
positions: Position[]
signals: LightSignal[]
walletBalances?: KeyValuePairOfDateTimeAndDecimal[] | null
indicatorsValues?: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; } | null;
walletBalances?: { key: Date; value: number }[] | null
indicatorsValues?: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase } | null
stream?: Candle | null
width?: number
height?: number
@@ -688,6 +687,55 @@ const TradeChart = ({
paneCount++
}
if (indicatorsValues?.StochasticCross != null) {
const stochKSeries = chart.current.addLineSeries({
color: theme.primary,
lineWidth: 1,
priceLineVisible: false,
priceLineWidth: 1,
title: '%K',
pane: paneCount,
priceFormat: {
precision: 2,
type: 'price',
},
})
const stochK = indicatorsValues.StochasticCross.stoch?.map((w) => {
return {
time: moment(w.date).unix(),
value: w.k,
}
})
// @ts-ignore
stochKSeries.setData(stochK)
const stochDSeries = chart.current.addLineSeries({
color: theme.info,
lineWidth: 1,
priceLineVisible: false,
priceLineWidth: 1,
lineStyle: LineStyle.Dotted,
title: '%D',
pane: paneCount,
priceFormat: {
precision: 2,
type: 'price',
},
})
const stochD = indicatorsValues.StochasticCross.stoch?.map((w) => {
return {
time: moment(w.date).unix(),
value: w.d,
}
})
// @ts-ignore
stochDSeries.setData(stochD)
paneCount++
}
if (indicatorsValues?.StDev != null) {
const stDevSeries = chart.current.addLineSeries({
color: theme.primary,

View File

@@ -4963,6 +4963,8 @@ export interface LightIndicator {
smoothPeriods?: number | null;
stochPeriods?: number | null;
cyclePeriods?: number | null;
kFactor?: number | null;
dFactor?: number | null;
}
export enum IndicatorType {
@@ -4976,6 +4978,7 @@ export enum IndicatorType {
EmaTrend = "EmaTrend",
Composite = "Composite",
StochRsiTrend = "StochRsiTrend",
StochasticCross = "StochasticCross",
Stc = "Stc",
StDev = "StDev",
LaggingStc = "LaggingStc",
@@ -5569,6 +5572,8 @@ export interface IndicatorBase {
smoothPeriods?: number | null;
stochPeriods?: number | null;
cyclePeriods?: number | null;
kFactor?: number | null;
dFactor?: number | null;
user?: User | null;
}

View File

@@ -429,6 +429,8 @@ export interface LightIndicator {
smoothPeriods?: number | null;
stochPeriods?: number | null;
cyclePeriods?: number | null;
kFactor?: number | null;
dFactor?: number | null;
}
export enum IndicatorType {
@@ -442,6 +444,7 @@ export enum IndicatorType {
EmaTrend = "EmaTrend",
Composite = "Composite",
StochRsiTrend = "StochRsiTrend",
StochasticCross = "StochasticCross",
Stc = "Stc",
StDev = "StDev",
LaggingStc = "LaggingStc",
@@ -1035,6 +1038,8 @@ export interface IndicatorBase {
smoothPeriods?: number | null;
stochPeriods?: number | null;
cyclePeriods?: number | null;
kFactor?: number | null;
dFactor?: number | null;
user?: User | null;
}

View File

@@ -103,6 +103,7 @@ const ALL_INDICATORS = [
IndicatorType.LaggingStc,
IndicatorType.SuperTrendCrossEma,
IndicatorType.DualEmaCross,
IndicatorType.StochasticCross,
]
// Indicator type to parameter mapping
@@ -119,6 +120,7 @@ const INDICATOR_PARAM_MAPPING = {
[IndicatorType.SuperTrendCrossEma]: ['period', 'multiplier'],
[IndicatorType.ChandelierExit]: ['period', 'multiplier'],
[IndicatorType.StochRsiTrend]: ['period', 'stochPeriods', 'signalPeriods', 'smoothPeriods'],
[IndicatorType.StochasticCross]: ['stochPeriods', 'signalPeriods', 'smoothPeriods', 'kFactor', 'dFactor'],
[IndicatorType.Stc]: ['cyclePeriods', 'fastPeriods', 'slowPeriods'],
[IndicatorType.LaggingStc]: ['cyclePeriods', 'fastPeriods', 'slowPeriods'],
}

View File

@@ -4,17 +4,17 @@ import {useQuery} from '@tanstack/react-query'
import useApiUrlStore from '../../app/store/apiStore'
import {
BacktestClient,
GeneticCrossoverMethod,
GeneticMutationMethod,
type GeneticRequest,
GeneticSelectionMethod,
IndicatorType,
type LightBacktestResponse,
type PaginatedBacktestsResponse,
type RunGeneticRequest,
Ticker,
Timeframe,
BacktestClient,
GeneticCrossoverMethod,
GeneticMutationMethod,
type GeneticRequest,
GeneticSelectionMethod,
IndicatorType,
type LightBacktestResponse,
type PaginatedBacktestsResponse,
type RunGeneticRequest,
Ticker,
Timeframe,
} from '../../generated/ManagingApi'
import {Toast} from '../../components/mollecules'
import Table from '../../components/mollecules/Table/Table'
@@ -42,6 +42,7 @@ const ALL_INDICATORS = [
IndicatorType.LaggingStc,
IndicatorType.SuperTrendCrossEma,
IndicatorType.DualEmaCross,
IndicatorType.StochasticCross,
]
// Form Interface

View File

@@ -414,6 +414,88 @@ const IndicatorList: React.FC = () => {
</div>
</>
) : null}
{indicatorType == IndicatorType.StochasticCross ? (
<>
<div className="form-control">
<div className="input-group">
<label htmlFor="stochPeriods" className="label mr-6">
Stoch Periods
</label>
<label className="input-group">
<input
type="number"
placeholder="14"
className="input"
{...register('stochPeriods')}
/>
</label>
</div>
</div>
<div className="form-control">
<div className="input-group">
<label htmlFor="signalPeriods" className="label mr-6">
Signal Periods
</label>
<label className="input-group">
<input
type="number"
placeholder="3"
className="input"
{...register('signalPeriods')}
/>
</label>
</div>
</div>
<div className="form-control">
<div className="input-group">
<label htmlFor="smoothPeriods" className="label mr-6">
Smooth Periods
</label>
<label className="input-group">
<input
type="number"
placeholder="3"
className="input"
{...register('smoothPeriods')}
/>
</label>
</div>
</div>
<div className="form-control">
<div className="input-group">
<label htmlFor="kFactor" className="label mr-6">
K Factor
</label>
<label className="input-group">
<input
type="number"
step="0.1"
placeholder="3.0"
className="input"
{...register('kFactor')}
/>
</label>
</div>
</div>
<div className="form-control">
<div className="input-group">
<label htmlFor="dFactor" className="label mr-6">
D Factor
</label>
<label className="input-group">
<input
type="number"
step="0.1"
placeholder="2.0"
className="input"
{...register('dFactor')}
/>
</label>
</div>
</div>
</>
) : null}
<div className="modal-action">
<button type="submit" className="btn">
Build