Add command for adding indicators

This commit is contained in:
2025-11-24 10:05:16 +07:00
parent 9e3d8c74b9
commit ad3b3f2fa5

View File

@@ -0,0 +1,415 @@
# build-indicator
## When to Use
Use this command when you need to:
- Create new technical indicators based on pattern descriptions
- Add signal, trend, or context indicators to the trading system
- Update all related files and configurations automatically
- Follow the established indicator architecture and conventions
## Prerequisites
- Clear indicator specification with Type, Label, Core Logic, Triggers, and Parameters
- Understanding of indicator categories (Signal/Trend/Context)
- Access to existing indicator implementations for reference
- Knowledge of the indicator's mathematical calculations
## Execution Steps
### Step 1: Parse Indicator Specification
Analyze the indicator description and extract:
**Required Information:**
- **Type**: Signal/Trend/Context (determines folder location)
- **Label**: Indicator name (e.g., "Stochastic Filtered")
- **Core Logic**: Technical description of what the indicator does
- **Trigger Conditions**: When to generate signals (for Signal indicators)
- **Parameters**: Configuration values with defaults
- **Signal Type**: Long/Short for Signal indicators, Confidence levels for Context
**Example Format:**
```
Type: Signal
Label: Stochastic Filtered
Core Logic: Generates signals by filtering %K / %D crossovers to occur only within extreme overbought (above 80) or oversold (below 20) zones.
Trigger a Long when → The %K line crosses above the %D line (bullish momentum shift). The crossover occurs in the oversold zone (both %K and %D lines are below 20).
Trigger a Short when → The %K line crosses below the %D line (bearish momentum shift). The crossover occurs in the overbought zone (both %K and %D lines are above 80).
Parameters:
%K Period (default: 14)
%K Slowing (default: 3)
%D Period (default: 3)
Oversold Threshold: 20
Overbought Threshold: 80
```
### Step 2: Determine Implementation Details
**Check Existing Indicators:**
- Search codebase: `grep -r "Get{IndicatorType}" src/Managing.Domain/Indicators/`
- Look for similar Skender.Stock.Indicators usage patterns
- Check if candle mapping logic can be shared with existing indicators
**Class Name Convention:**
- Signal indicators: `{IndicatorName}.cs` (e.g., `StochasticFiltered.cs`)
- Trend indicators: `{IndicatorName}.cs` (e.g., `EmaTrend.cs`)
- Context indicators: `{IndicatorName}.cs` (e.g., `StDev.cs`)
**Inheritance Strategy:**
- Default: Extend `IndicatorBase` directly
- Shared Mapping: Extend from existing shared base class if mappings overlap
- New Shared Base: Create base class only if multiple indicators will share the same mapping
**Class Name Pattern:**
- For signal/trend indicators: Class name = `{IndicatorName}` (inherits from `IndicatorBase` or shared base)
- For context indicators: Class name = `{IndicatorName}` (inherits from `IndicatorBase` or shared base)
**Location:**
- Signal → `src/Managing.Domain/Indicators/Signals/`
- Trend → `src/Managing.Domain/Indicators/Trends/`
- Context → `src/Managing.Domain/Indicators/Context/`
**Enum Name:**
- Convert label to PascalCase: `StochasticFiltered`
- Add to `IndicatorType` enum in `src/Managing.Common/Enums.cs`
### Step 3: Implement Indicator Class
Create the indicator class following the established pattern. Check if other indicators use similar candle mappings - if so, consider creating or extending a base class.
**Check for Existing Candle Mappings:**
- Search for similar indicator types that might share candle mappings
- If another indicator uses the same Skender.Stock.Indicators result type, consider extending an existing base class or creating a shared base class
- Only create a new base class if no other indicator shares the same candle mapping pattern
**Base Structure:**
```csharp
using Managing.Core;
using Managing.Domain.Candles;
using Managing.Domain.Indicators;
using Managing.Domain.Shared.Rules;
using Managing.Domain.Strategies.Base;
using Skender.Stock.Indicators;
using static Managing.Common.Enums;
namespace Managing.Domain.Strategies.{TypeFolder};
public class {IndicatorName} : IndicatorBase
{
public List<LightSignal> Signals { get; set; }
public {IndicatorName}(string name, {parameters}) :
base(name, IndicatorType.{EnumName})
{
Signals = new List<LightSignal>();
// Initialize parameters
}
// Implementation methods...
}
```
**Shared Base Class Pattern (use only if mapping is shared):**
If another indicator uses the same candle result mapping, extend from a shared base class:
```csharp
public class {SharedBaseName}Base : IndicatorBase
{
// Shared candle mapping logic here
protected List<{CandleResultType}> Map{Indicator}ToCandle(List<{SkenderResult}> results, IEnumerable<Candle> candles)
{
// Shared mapping implementation
}
}
public class {IndicatorName} : {SharedBaseName}Base
{
// Indicator-specific logic only
}
```
**Key Methods to Implement:**
1. `Run(HashSet<Candle> candles)` - Main calculation logic
2. `Run(HashSet<Candle> candles, IndicatorsResultBase preCalculatedValues)` - Optimized version
3. `GetIndicatorValues(HashSet<Candle> candles)` - Return calculated values
4. Private processing methods for signal generation
**Signal Generation Pattern:**
```csharp
private void ProcessSignals(List<{Indicator}Result> results, HashSet<Candle> candles)
{
var mappedData = Map{Indicator}ToCandle(results, candles);
if (mappedData.Count == 0) return;
var previousCandle = mappedData[0];
foreach (var currentCandle in mappedData.Skip(1))
{
// Check trigger conditions
if (/* Long condition */)
{
AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
}
if (/* Short condition */)
{
AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
}
previousCandle = currentCandle;
}
}
```
### Step 4: Update Configuration Files
**Update Enums.cs:**
```csharp
public enum IndicatorType
{
// ... existing indicators
StochasticFiltered,
// ... continue
}
```
**Update ScenarioHelpers.cs:**
- Add case to `BuildIndicator()` method: `IndicatorType.{EnumName} => new {IndicatorName}(indicator.Name, {parameters})`
- Add case to `GetSignalType()` method: `IndicatorType.{EnumName} => SignalType.{Type}`
- Add parameters to `BuildIndicator()` overload if needed
**Update GeneticService.cs:**
- Add default values to `DefaultIndicatorValues`: `[IndicatorType.{EnumName}] = new() { {param_mappings} }`
- Add parameter ranges to `IndicatorParameterRanges`: `[IndicatorType.{EnumName}] = new() { {param_ranges} }`
- Add parameter mapping to `IndicatorParamMapping`: `[IndicatorType.{EnumName}] = [{param_names}]`
### Step 5: Test and Validate
**Compile Check:**
```bash
dotnet build
```
**Basic Validation:**
- Verify indicator appears in GeneticService configurations
- Check that BuildIndicator methods work correctly
- Ensure proper SignalType assignment
**Integration Test:**
- Create a simple backtest using the new indicator
- Verify signals are generated correctly
- Check parameter handling and validation
## Available Skender.Stock.Indicators
The following indicators are available from the [Skender.Stock.Indicators](https://dotnet.stockindicators.dev/) library and can be used as the basis for custom trading indicators:
### Trend Indicators
- **EMA (Exponential Moving Average)**: `GetEma(period)` - Smooths price data with exponential weighting
- **SMA (Simple Moving Average)**: `GetSma(period)` - Arithmetic mean of prices over period
- **WMA (Weighted Moving Average)**: `GetWma(period)` - Weighted average favoring recent prices
- **HMA (Hull Moving Average)**: `GetHma(period)` - Responsive moving average using WMA
- **DEMA (Double Exponential Moving Average)**: `GetDema(period)` - Two EMAs for reduced lag
- **TEMA (Triple Exponential Moving Average)**: `GetTema(period)` - Three EMAs for further lag reduction
- **VWMA (Volume Weighted Moving Average)**: `GetVwma(period)` - Volume-weighted price average
### Momentum Oscillators
- **RSI (Relative Strength Index)**: `GetRsi(period)` - Momentum oscillator (0-100)
- **Stochastic Oscillator**: `GetStoch(kPeriod, kSlowing, dPeriod)` - %K and %D lines
- **Stochastic RSI**: `GetStochRsi(rsiPeriod, stochPeriod, signalPeriod, smoothPeriod)` - Stochastic of RSI
- **Williams %R**: `GetWilliamsR(period)` - Momentum oscillator (-100 to 0)
- **CCI (Commodity Channel Index)**: `GetCci(period)` - Mean deviation from average price
- **MFI (Money Flow Index)**: `GetMfi(period)` - Volume-weighted RSI
- **AO (Awesome Oscillator)**: `GetAo()` - MACD of median price
- **KVO (Klinger Volume Oscillator)**: `GetKvo(fastPeriod, slowPeriod, signalPeriod)` - Volume oscillator
### Trend Following
- **MACD (Moving Average Convergence Divergence)**: `GetMacd(fastPeriod, slowPeriod, signalPeriod)` - Trend momentum indicator
- **SuperTrend**: `GetSuperTrend(period, multiplier)` - ATR-based trailing stop
- **Chandelier Exit**: `GetChandelier(period, multiplier, type)` - ATR-based exit levels
- **Parabolic SAR**: `GetParabolicSar(accelerationStep, maxAcceleration)` - Trailing stop and reversal
- **ADX (Average Directional Index)**: `GetAdx(period)` - Trend strength indicator
- **DMI (Directional Movement Index)**: `GetDmi(period)` - Trend direction and strength
- **PSAR (Parabolic SAR)**: `GetPsar(accelerationStep, maxAcceleration)` - Dynamic support/resistance
### Volatility Indicators
- **ATR (Average True Range)**: `GetAtr(period)` - Volatility measurement
- **Bollinger Bands**: `GetBollingerBands(period, standardDeviations)` - Price volatility bands
- **Standard Deviation**: `GetStdDev(period)` - Statistical volatility measure
- **TR (True Range)**: `GetTr()` - Maximum price movement range
### Volume Indicators
- **OBV (On Balance Volume)**: `GetObv()` - Cumulative volume based on price direction
- **CMF (Chaikin Money Flow)**: `GetCmf(period)` - Volume-weighted price trend
- **ADL (Accumulation/Distribution Line)**: `GetAdl()` - Volume-based price accumulation
- **EMV (Ease of Movement)**: `GetEmv(period)` - Price movement relative to volume
- **NVI (Negative Volume Index)**: `GetNvi()` - Volume-based trend indicator
### Cycle Indicators
- **STC (Schaff Trend Cycle)**: `GetStc(cyclePeriod, fastPeriod, slowPeriod)` - Cycle oscillator (0-100)
- **DPO (Detrended Price Oscillator)**: `GetDpo(period)` - Removes trend from price
- **EPMA (Endpoint Moving Average)**: `GetEpma(period)` - End-point moving average
### Support/Resistance
- **Pivot Points**: `GetPivotPoints(period)` - Traditional pivot levels
- **Fibonacci Retracements**: `GetFibonacciRetracements()` - Fibonacci ratio levels
### Candlestick Patterns
- **Doji**: `GetDoji()` - Doji candlestick patterns
- **Hammer**: `GetHammer()` - Hammer patterns
- **Engulfing**: `GetEngulfing()` - Bullish/bearish engulfing
- **Marubozu**: `GetMarubozu()` - Marubozu patterns
- **And many more...**
### Usage Examples
```csharp
// Basic usage
var ema = candles.GetEma(20).ToList();
var macd = candles.GetMacd(12, 26, 9).ToList();
var rsi = candles.GetRsi(14).ToList();
var stoch = candles.GetStoch(14, 3, 3).ToList();
var superTrend = candles.GetSuperTrend(10, 3.0).ToList();
// Chain indicators (indicator of indicators)
var rsiOfObv = candles.GetObv().GetRsi(14).ToList();
var smaOfRsi = candles.GetRsi(14).GetSma(9).ToList();
```
For complete documentation and examples, visit: [Skender.Stock.Indicators Guide](https://dotnet.stockindicators.dev/guide/)
### Finding the Right Method
When implementing a new indicator, search the [Skender documentation](https://dotnet.stockindicators.dev/indicators/) for your indicator concept:
1. **Identify the core calculation**: What mathematical formula does your indicator use?
2. **Find the Skender equivalent**: Search for methods like `Get{IndicatorName}()`
3. **Check parameters**: Most indicators follow common patterns:
- `period`: Lookback period (typically 5-300)
- `fastPeriod`/`slowPeriod`: For dual moving averages
- `signalPeriod`: For signal line calculations
- `multiplier`: ATR multipliers (typically 1.0-5.0)
4. **Verify result structure**: Check what properties the result object contains
### Parameter Guidelines
**Common Ranges by Indicator Type:**
- **Moving Averages**: Period 5-300 (shorter = responsive, longer = smooth)
- **Oscillators**: Period 5-50 (RSI: 14, Stoch: 14, CCI: 20)
- **Trend Following**: Period 10-50, Multiplier 1.0-5.0
- **Volatility**: Period 5-50, Standard Deviations 1.0-3.0
- **Volume**: Period 5-50 (OBV uses no period)
**Testing Parameters:**
- Start with industry standard defaults
- Test multiple parameter combinations
- Consider timeframe: Shorter timeframes may need smaller periods
### Result Object Patterns
Different indicators return different result objects. Common patterns:
**Single Value Results:**
- `EmaResult`: `{ Date, Ema }`
- `RsiResult`: `{ Date, Rsi }`
- `AtrResult`: `{ Date, Atr }`
- `ObvResult`: `{ Date, Obv }`
**Dual Value Results:**
- `StochResult`: `{ Date, PercentK, PercentD, Oscillator }`
- `MacdResult`: `{ Date, Macd, Signal, Histogram }`
- `StochRsiResult`: `{ Date, Rsi, StochRsi, Signal }`
**Triple+ Value Results:**
- `BollingerBandsResult`: `{ Date, Sma, UpperBand, LowerBand }`
- `SuperTrendResult`: `{ Date, SuperTrend, UpperBand, LowerBand }`
- `ChandelierResult`: `{ Date, ChandelierExit }`
**Candlestick Results:**
- `CandleResult`: `{ Date, Price, Match, Candle }` (for pattern recognition)
When creating your `Candle{Indicator}` mapping class, include all relevant result properties plus the base Candle properties (Close, Open, Date, Ticker, Exchange).
### Quick Reference - Currently Used Indicators
**In This Codebase:**
- `GetEma(period)``EmaResult` - Used in EMA Trend, EMA Cross, Dual EMA Cross
- `GetMacd(fast, slow, signal)``MacdResult` - Used in MACD Cross
- `GetRsi(period)``RsiResult` - Used in RSI Divergence variants
- `GetStoch(kPeriod, kSlowing, dPeriod)``StochResult` - Used in Stochastic Filtered
- `GetStochRsi(rsiPeriod, stochPeriod, signalPeriod, smoothPeriod)``StochRsiResult` - Used in Stoch RSI Trend
- `GetSuperTrend(period, multiplier)``SuperTrendResult` - Used in SuperTrend, SuperTrend Cross EMA
- `GetStc(cyclePeriod, fastPeriod, slowPeriod)``StcResult` - Used in STC, Lagging STC
- `GetStdDev(period)``StdDevResult` - Used in StDev Context
- `GetChandelier(period, multiplier, type)``ChandelierResult` - Used in Chandelier Exit
- `GetAdx(period)``AdxResult` - Used in SuperTrend Cross EMA
**Available But Unused:**
- `GetBollingerBands(period, stdDev)``BollingerBandsResult`
- `GetAtr(period)``AtrResult`
- `GetObv()``ObvResult`
- `GetCci(period)``CciResult`
- `GetMfi(period)``MfiResult`
- And many more... (see full list above)
## Common Patterns
### Signal Indicator Pattern
- Uses `TradeDirection.Long`/`Short` with `Confidence` levels
- Implements crossover or threshold-based logic
- Returns filtered signals only when conditions are met
### Trend Indicator Pattern
- Uses `TradeDirection.Long`/`Short` for trend direction
- Continuous assessment rather than discrete signals
- Lower confidence levels for trend indicators
### Context Indicator Pattern
- Uses `Confidence.None`/`Low`/`Medium`/`High` for veto power
- Acts as filter for other indicators
- No directional signals, only context assessment
### Shared Base Class Pattern
**When to Use:**
- Multiple indicators use the same Skender.Stock.Indicators result type
- Indicators share identical candle mapping logic
- Common signal processing patterns exist
**Example:**
```csharp
public abstract class StochasticBase : IndicatorBase
{
protected List<CandleStoch> MapStochToCandle(List<StochResult> stochResults, IEnumerable<Candle> candles)
{
// Shared mapping logic for all Stochastic-based indicators
}
}
public class StochasticFiltered : StochasticBase { /* Specific logic */ }
public class AnotherStochasticIndicator : StochasticBase { /* Specific logic */ }
```
**When NOT to Use:**
- Indicators have different result types (Stoch vs StochRsi)
- Mapping logic differs significantly
- Only one indicator uses a particular pattern
## Error Handling
**Common Issues:**
- Missing parameters in constructor
- Incorrect SignalType assignment
- Wrong folder location (Signals/Trends/Context)
- Missing enum updates
- Parameter range mismatches
**Validation Checklist:**
- [ ] Checked for existing indicators with similar candle mappings
- [ ] Used appropriate base class (IndicatorBase or shared base if mappings overlap)
- [ ] Constructor parameters match IIndicator interface
- [ ] SignalType correctly assigned
- [ ] Enum added to IndicatorType
- [ ] BuildIndicator methods updated
- [ ] GeneticService configurations updated
- [ ] Compiles without errors