caishen

IDS - Indicator Data Services

RISE Framework Specification

Spec ID: 05
Version: 1.0
Document ID: caishen-rise-ids-v1.0
Last Updated: 2025-01-31

Creative Intent

What IDS Enables Users to Create:

Desired Outcomes:

  1. Users can calculate any supported indicator on price data
  2. Indicator results are consistent and validated
  3. New indicators can be added following established patterns
  4. ML models can consume indicator features

Core Indicators

Bill Williams Indicators

Alligator

Three smoothed moving averages representing market states:

Algorithm Alligator(quotes):
  Jaw = SMMA(quotes, 13).Shift(8)
  Teeth = SMMA(quotes, 8).Shift(5)
  Lips = SMMA(quotes, 5).Shift(3)
  Return (Jaw, Teeth, Lips)

AlligatorResult:

AlligatorResult:
  - Date: DateTime
  - Jaw: decimal?
  - Teeth: decimal?
  - Lips: decimal?

Awesome Oscillator (AO)

Difference between 5-period and 34-period SMA of median price.

Algorithm AwesomeOscillator(quotes):
  MedianPrice = (High + Low) / 2
  FastSMA = SMA(MedianPrice, 5)
  SlowSMA = SMA(MedianPrice, 34)
  AO = FastSMA - SlowSMA
  Return AO

AwesomeResult:

AwesomeResult:
  - Date: DateTime
  - Oscillator: double?
  - Normalized: double?    # Optional normalized value

Accelerator Oscillator (AC)

AO minus 5-period SMA of AO.

Algorithm Accelerator(quotes):
  AO = AwesomeOscillator(quotes)
  AC = AO - SMA(AO, 5)
  Return AC

AcceleratorResult:

AcceleratorResult:
  - Date: DateTime
  - Oscillator: double?

Gator Oscillator

Visual representation of Alligator convergence/divergence.

Algorithm Gator(quotes):
  Alligator = GetAlligator(quotes)
  Upper = Abs(Jaw - Teeth)
  Lower = -Abs(Teeth - Lips)
  Return (Upper, Lower)

GatorResult:

GatorResult:
  - Date: DateTime
  - Upper: decimal?       # Jaw-Teeth difference
  - Lower: decimal?       # Teeth-Lips difference (negative)
  - UpperIsGrowing: bool?
  - LowerIsGrowing: bool?

Fractal

Local high/low patterns indicating potential reversal points.

Algorithm Fractal(quotes, windowSpan=2):
  For each bar with N bars on each side:
    If bar.High > all surrounding highs:
      FractalBear = bar.High
    If bar.Low < all surrounding lows:
      FractalBull = bar.Low
  Return results

FractalResult:

FractalResult:
  - Date: DateTime
  - FractalBear: decimal?   # High point (sell signal)
  - FractalBull: decimal?   # Low point (buy signal)

Zone Calculation

Determines trading zone based on AO and AC values.

Algorithm Zone(ao, ac, prevAo, prevAc):
  aoGreen = ao > prevAo
  acGreen = ac > prevAc
  
  If aoGreen AND acGreen:
    Return Zone.Green    # Strong buy
  Else If NOT aoGreen AND NOT acGreen:
    Return Zone.Red      # Strong sell
  Else:
    Return Zone.Gray     # Neutral

ZoneEnum:

ZoneEnum:
  - Gray = 0     # Neutral
  - Green = 1    # Buy momentum
  - Red = 2      # Sell momentum

Market Facilitation Index (MFI)

Measures price movement efficiency.

Algorithm MFI(bar, prevBar):
  Range = bar.High - bar.Low
  MFI = Range / bar.Volume
  
  volumeUp = bar.Volume > prevBar.Volume
  mfiUp = MFI > prevMFI
  
  If volumeUp AND mfiUp: Return "Green"     # Strong trend
  If volumeUp AND NOT mfiUp: Return "Squat" # Consolidation
  If NOT volumeUp AND mfiUp: Return "Fade"  # Weak trend
  If NOT volumeUp AND NOT mfiUp: Return "Fake" # No interest

Service Interface

IIndicatorService

Interface IIndicatorService:

  Method GetAlligator:
    Input: List<IQuote>
    Output: List<AlligatorResult>
    
  Method GetAwesomeOscillator:
    Input: List<IQuote>
    Output: List<AwesomeResult>
    
  Method GetAccelerator:
    Input: List<IQuote>
    Output: List<AcceleratorResult>
    
  Method GetGator:
    Input: List<IQuote>
    Output: List<GatorResult>
    
  Method GetFractal:
    Input: List<IQuote>, windowSpan: int
    Output: List<FractalResult>
    
  Method CalculateAllIndicators:
    Input: List<IQuote>
    Output: List<BarChaosItem>

IQuote Interface

All indicators consume data implementing IQuote:

Interface IQuote:
  - Date: DateTime
  - Open: decimal
  - High: decimal
  - Low: decimal
  - Close: decimal
  - Volume: decimal

Creative Advancement Scenarios

Scenario 1: Calculate Complete Indicator Set

Creative Advancement Scenario: Generate All Indicators for CDB

Desired Outcome: All chaos indicators calculated for price series

Current Reality: Raw OHLCV data available

Natural Progression Steps:
  1. Receive price history as List<IQuote>
  2. Calculate Alligator (Lips, Teeth, Jaw)
  3. Calculate AO
  4. Calculate AC
  5. Detect Fractals
  6. Calculate Zones
  7. Calculate MFI
  8. Merge into BarChaosItem list

Achieved Outcome: Complete indicator data for charting

Supporting Features: IndicatorService, indicator library

Scenario 2: AO Peak Detection

Creative Advancement Scenario: Identify AO Peaks

Desired Outcome: List of AO peaks for divergence analysis

Current Reality: AO values calculated

Natural Progression Steps:
  1. Scan AO series for local maxima/minima
  2. Apply minimum separation threshold
  3. Classify as bull/bear peak
  4. Record peak date and value
  5. Return peak list

Achieved Outcome: AO peaks identified for divergence

Supporting Features: AOPeak entity, peak detection algorithm

Indicator Calculation Pipeline

┌─────────────────┐
│  Price History  │
│   (IQuote[])    │
└────────┬────────┘
         │
         ▼
┌─────────────────────────────────────────────┐
│             Indicator Pipeline              │
│  ┌─────────┐  ┌─────────┐  ┌─────────────┐ │
│  │Alligator│  │   AO    │  │     AC      │ │
│  │ (SMMA)  │  │ (5/34)  │  │ (AO-SMA5)   │ │
│  └────┬────┘  └────┬────┘  └──────┬──────┘ │
│       │            │              │         │
│       ▼            ▼              ▼         │
│  ┌─────────┐  ┌─────────┐  ┌─────────────┐ │
│  │  Gator  │  │ Fractal │  │    Zone     │ │
│  │ (Upper/ │  │ (H/L    │  │  (AO/AC     │ │
│  │ Lower)  │  │ pattern)│  │  direction) │ │
│  └────┬────┘  └────┬────┘  └──────┬──────┘ │
│       │            │              │         │
└───────┴────────────┴──────────────┴─────────┘
                     │
                     ▼
           ┌─────────────────┐
           │  BarChaosItem[] │
           │ (Complete Data) │
           └─────────────────┘

SMMA (Smoothed Moving Average)

Algorithm SMMA(values, period):
  For first period bars:
    SMMA = SMA(values, period)
  For subsequent bars:
    SMMA[i] = (SMMA[i-1] * (period-1) + value[i]) / period
  Return SMMA

Implementation Notes for Python/TypeScript

Python Implementation

from dataclasses import dataclass
from datetime import datetime
from typing import List, Optional, Protocol
from decimal import Decimal

class IQuote(Protocol):
    date: datetime
    open: Decimal
    high: Decimal
    low: Decimal
    close: Decimal
    volume: int

@dataclass
class AlligatorResult:
    date: datetime
    jaw: Optional[float] = None
    teeth: Optional[float] = None
    lips: Optional[float] = None

@dataclass
class AwesomeResult:
    date: datetime
    oscillator: Optional[float] = None

@dataclass
class FractalResult:
    date: datetime
    fractal_bear: Optional[float] = None
    fractal_bull: Optional[float] = None

class Indicator:
    @staticmethod
    def alligator(
        quotes: List[IQuote],
        jaw_periods: int = 13,
        teeth_periods: int = 8,
        lips_periods: int = 5
    ) -> List[AlligatorResult]:
        """Calculate Alligator indicator"""
        pass
    
    @staticmethod
    def awesome_oscillator(
        quotes: List[IQuote],
        fast_period: int = 5,
        slow_period: int = 34
    ) -> List[AwesomeResult]:
        """Calculate Awesome Oscillator"""
        pass
    
    @staticmethod
    def fractal(
        quotes: List[IQuote],
        window_span: int = 2
    ) -> List[FractalResult]:
        """Detect Williams fractals"""
        results = []
        n = len(quotes)
        
        for i in range(window_span, n - window_span):
            q = quotes[i]
            is_high = True
            is_low = True
            
            for j in range(i - window_span, i + window_span + 1):
                if j == i:
                    continue
                wing = quotes[j]
                if q.high <= wing.high:
                    is_high = False
                if q.low >= wing.low:
                    is_low = False
            
            result = FractalResult(date=q.date)
            if is_high:
                result.fractal_bear = float(q.high)
            if is_low:
                result.fractal_bull = float(q.low)
            results.append(result)
        
        return results

TypeScript Implementation

interface IQuote {
  date: Date;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
}

interface AlligatorResult {
  date: Date;
  jaw?: number;
  teeth?: number;
  lips?: number;
}

interface AwesomeResult {
  date: Date;
  oscillator?: number;
}

interface FractalResult {
  date: Date;
  fractalBear?: number;
  fractalBull?: number;
}

class Indicator {
  static alligator(
    quotes: IQuote[],
    jawPeriods = 13,
    teethPeriods = 8,
    lipsPeriods = 5
  ): AlligatorResult[] {
    // Implementation
    return [];
  }
  
  static awesomeOscillator(
    quotes: IQuote[],
    fastPeriod = 5,
    slowPeriod = 34
  ): AwesomeResult[] {
    // Implementation
    return [];
  }
  
  static fractal(
    quotes: IQuote[],
    windowSpan = 2
  ): FractalResult[] {
    const results: FractalResult[] = [];
    const n = quotes.length;
    
    for (let i = windowSpan; i < n - windowSpan; i++) {
      const q = quotes[i];
      let isHigh = true;
      let isLow = true;
      
      for (let j = i - windowSpan; j <= i + windowSpan; j++) {
        if (j === i) continue;
        const wing = quotes[j];
        if (q.high <= wing.high) isHigh = false;
        if (q.low >= wing.low) isLow = false;
      }
      
      const result: FractalResult = { date: q.date };
      if (isHigh) result.fractalBear = q.high;
      if (isLow) result.fractalBull = q.low;
      results.push(result);
    }
    
    return results;
  }
}