///|
pub(all) enum DataSource {
  TradingView
  Mt5
  Yfinance
  AkShare
  Fixture
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) enum Direction {
  Bullish
  Bearish
  Neutral
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) enum CyclePosition {
  Spike
  MicroChannel
  TightChannel
  NormalChannel
  BroadChannel
  TrendingRange
  TradingRange
  ExtremeRange
  UnknownCycle
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) enum MarketPhase {
  Stable
  Transitioning
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct KlineBar {
  seq : Int
  open : Double
  high : Double
  low : Double
  close : Double
  volume : Double
  closed : Bool
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct KlineSnapshot {
  source_id : SourceId
  data_source : DataSource
  symbol : Symbol
  timeframe : Timeframe
  captured_at_ms : Int64
  bars : Array[KlineBar]
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct MarketFeatureFrame {
  source_id : SourceId
  closed_bar_count : Int
  atr : Double?
  ema_fast : Double?
  ema_slow : Double?
  warmup_complete : Bool
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn kline_bar(
  seq : Int,
  open : Double,
  high : Double,
  low : Double,
  close : Double,
  volume? : Double = 0.0,
  closed? : Bool = true,
) -> KlineBar {
  { seq, open, high, low, close, volume, closed }
}

///|
pub fn kline_snapshot(
  source_id : SourceId,
  data_source : DataSource,
  symbol : Symbol,
  timeframe : Timeframe,
  captured_at_ms : Int64,
  bars : Array[KlineBar],
) -> KlineSnapshot {
  { source_id, data_source, symbol, timeframe, captured_at_ms, bars }
}

///|
pub fn KlineSnapshot::closed_bar_count(self : KlineSnapshot) -> Int {
  self.bars.fold(init=0, fn(total, bar) {
    if bar.closed {
      total + 1
    } else {
      total
    }
  })
}

///|
pub fn market_feature_frame(
  source_id : SourceId,
  closed_bar_count : Int,
  atr : Double?,
  ema_fast : Double?,
  ema_slow : Double?,
  warmup_complete? : Bool = false,
) -> MarketFeatureFrame {
  { source_id, closed_bar_count, atr, ema_fast, ema_slow, warmup_complete }
}