//! TA-Lib function metadata registry — the Rust abstract / introspection layer.
//!
//! GENERATED by ta_codegen (`backends/rust_abstract.rs`) — do not edit by hand.
//!
//! Rust analog of C's `ta_abstract` (`TA_GetFuncInfo`, `TA_Get*ParameterInfo`,
//! `TA_ForEachFunc`), implemented as a **zero-cost, link-time-const registry**:
//!   * all metadata is `&'static`/`const` in `.rodata` — zero heap, zero runtime init;
//!   * the opaque C `void* dataSet` + type tag becomes a type-safe [`OptDomain`] enum
//!     (illegal states unrepresentable, no unchecked cast);
//!   * [`FuncId`] is a fieldless enum that doubles as the dense index into [`FUNCS`]
//!     (no opaque handle, no magic-number validity check);
//!   * enumeration returns an iterator instead of C's fn-pointer + `void*` callback;
//!   * no heap allocation and no `*Alloc`/`*Free` pairs anywhere.
//!
//! Public names mirror C (`get_func_info`, `get_*_parameter_info`, `for_each_func`,
//! `groups`) so C porters are at home; the shapes are idiomatic Rust.
//!
//! ## Why name lookup uses a generated `match` (and not a hash map / `phf` / strcmp)
//!  * Lookup is a **cold path** — function discovery at setup, never per-bar compute.
//!  * rustc/LLVM lower a 161-arm `&str` `match` to a length-bucketed + leading-byte
//!    dispatch (not a comparison chain): effectively O(1), entirely in `.rodata`,
//!    zero allocation, zero dependencies.
//!  * For reference, C's `TA_GetFuncHandle` is an O(n) linear `strcmp` within a
//!    26-way first-letter bucket (up to 67 compares for the `CDL*` bucket) plus
//!    several pointer hops per entry. The generated `match` is strictly less work.
#![allow(clippy::all)]
#![allow(non_camel_case_types)]

use crate::FuncUnstId;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum FuncId {
    Accbands,
    Acos,
    Ad,
    Add,
    Adosc,
    Adx,
    Adxr,
    Apo,
    Aroon,
    Aroonosc,
    Asin,
    Atan,
    Atr,
    Avgdev,
    Avgprice,
    Bbands,
    Beta,
    Bop,
    Cci,
    Cdl2crows,
    Cdl3blackcrows,
    Cdl3inside,
    Cdl3linestrike,
    Cdl3outside,
    Cdl3starsinsouth,
    Cdl3whitesoldiers,
    Cdlabandonedbaby,
    Cdladvanceblock,
    Cdlbelthold,
    Cdlbreakaway,
    Cdlclosingmarubozu,
    Cdlconcealbabyswall,
    Cdlcounterattack,
    Cdldarkcloudcover,
    Cdldoji,
    Cdldojistar,
    Cdldragonflydoji,
    Cdlengulfing,
    Cdleveningdojistar,
    Cdleveningstar,
    Cdlgapsidesidewhite,
    Cdlgravestonedoji,
    Cdlhammer,
    Cdlhangingman,
    Cdlharami,
    Cdlharamicross,
    Cdlhighwave,
    Cdlhikkake,
    Cdlhikkakemod,
    Cdlhomingpigeon,
    Cdlidentical3crows,
    Cdlinneck,
    Cdlinvertedhammer,
    Cdlkicking,
    Cdlkickingbylength,
    Cdlladderbottom,
    Cdllongleggeddoji,
    Cdllongline,
    Cdlmarubozu,
    Cdlmatchinglow,
    Cdlmathold,
    Cdlmorningdojistar,
    Cdlmorningstar,
    Cdlonneck,
    Cdlpiercing,
    Cdlrickshawman,
    Cdlrisefall3methods,
    Cdlseparatinglines,
    Cdlshootingstar,
    Cdlshortline,
    Cdlspinningtop,
    Cdlstalledpattern,
    Cdlsticksandwich,
    Cdltakuri,
    Cdltasukigap,
    Cdlthrusting,
    Cdltristar,
    Cdlunique3river,
    Cdlupsidegap2crows,
    Cdlxsidegap3methods,
    Ceil,
    Cmo,
    Correl,
    Cos,
    Cosh,
    Dema,
    Div,
    Dx,
    Ema,
    Exp,
    Floor,
    HtDcperiod,
    HtDcphase,
    HtPhasor,
    HtSine,
    HtTrendline,
    HtTrendmode,
    Imi,
    Kama,
    Linearreg,
    LinearregAngle,
    LinearregIntercept,
    LinearregSlope,
    Ln,
    Log10,
    Ma,
    Macd,
    Macdext,
    Macdfix,
    Mama,
    Mavp,
    Max,
    Maxindex,
    Medprice,
    Mfi,
    Midpoint,
    Midprice,
    Min,
    Minindex,
    Minmax,
    Minmaxindex,
    MinusDi,
    MinusDm,
    Mom,
    Mult,
    Natr,
    Obv,
    PlusDi,
    PlusDm,
    Ppo,
    Roc,
    Rocp,
    Rocr,
    Rocr100,
    Rsi,
    Sar,
    Sarext,
    Sin,
    Sinh,
    Sma,
    Sqrt,
    Stddev,
    Stoch,
    Stochf,
    Stochrsi,
    Sub,
    Sum,
    T3,
    Tan,
    Tanh,
    Tema,
    Trange,
    Trima,
    Trix,
    Tsf,
    Typprice,
    Ultosc,
    Var,
    Wclprice,
    Willr,
    Wma,
}

impl FuncId {
    /// Number of functions in the registry.
    pub const COUNT: usize = 161;
    /// Metadata for this function (O(1) index into the const table).
    #[inline] pub fn info(self) -> &'static FuncInfo { &FUNCS[self as usize] }
    /// Upper-case TA name, e.g. "RSI".
    #[inline] pub fn name(self) -> &'static str { FUNCS[self as usize].name }
}

/// Function group (closed set — replaces C's runtime group-string table + linear `getGroupId`).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Group {
    CycleIndicators,
    MathOperators,
    MathTransform,
    MomentumIndicators,
    OverlapStudies,
    PatternRecognition,
    PriceTransform,
    StatisticFunctions,
    VolatilityIndicators,
    VolumeIndicators,
}

impl Group {
    /// All groups, in canonical order.
    pub const ALL: &'static [Group] = &[
        Group::CycleIndicators,
        Group::MathOperators,
        Group::MathTransform,
        Group::MomentumIndicators,
        Group::OverlapStudies,
        Group::PatternRecognition,
        Group::PriceTransform,
        Group::StatisticFunctions,
        Group::VolatilityIndicators,
        Group::VolumeIndicators,
    ];
    /// Canonical display string (matches C's `TA_GroupString` / the YAML `group`).
    pub const fn as_str(self) -> &'static str {
        match self {
            Group::CycleIndicators => "Cycle Indicators",
            Group::MathOperators => "Math Operators",
            Group::MathTransform => "Math Transform",
            Group::MomentumIndicators => "Momentum Indicators",
            Group::OverlapStudies => "Overlap Studies",
            Group::PatternRecognition => "Pattern Recognition",
            Group::PriceTransform => "Price Transform",
            Group::StatisticFunctions => "Statistic Functions",
            Group::VolatilityIndicators => "Volatility Indicators",
            Group::VolumeIndicators => "Volume Indicators",
        }
    }
}

/// Required-input data kind (C: `TA_Input_Price`/`Real`/`Integer`).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum InputType { Price, Real, Integer }

/// Output data kind (C: `TA_Output_Real`/`Integer`).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum OutputType { Real, Integer }

macro_rules! flag_newtype {
    ($name:ident { $($cn:ident = $cv:expr),* $(,)? }) => {
        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
        pub struct $name(pub u32);
        impl $name {
            $(pub const $cn: Self = Self($cv);)*
            /// Raw bits.
            #[inline] pub const fn bits(self) -> u32 { self.0 }
            /// True if all bits of `other` are set.
            #[inline] pub const fn contains(self, other: Self) -> bool { self.0 & other.0 == other.0 }
        }
    };
}

flag_newtype!(FuncFlags {
    OVERLAP = 0x0100_0000,
    VOLUME = 0x0400_0000,
    UNSTABLE_PERIOD = 0x0800_0000,
    CANDLESTICK = 0x1000_0000,
});
flag_newtype!(InputFlags {
    PRICE_OPEN = 0x0000_0001,
    PRICE_HIGH = 0x0000_0002,
    PRICE_LOW = 0x0000_0004,
    PRICE_CLOSE = 0x0000_0008,
    PRICE_VOLUME = 0x0000_0010,
    PRICE_OPENINTEREST = 0x0000_0020,
    PRICE_TIMESTAMP = 0x0000_0040,
});
flag_newtype!(OptInputFlags {
    IS_PERCENT = 0x0010_0000,
    IS_DEGREE = 0x0020_0000,
    IS_CURRENCY = 0x0040_0000,
    ADVANCED = 0x0100_0000,
});
flag_newtype!(OutputFlags {
    LINE = 0x0000_0001,
    DOT_LINE = 0x0000_0002,
    DASH_LINE = 0x0000_0004,
    DOT = 0x0000_0008,
    HISTO = 0x0000_0010,
    PATTERN_BOOL = 0x0000_0020,
    PATTERN_BULL_BEAR = 0x0000_0040,
    PATTERN_STRENGTH = 0x0000_0080,
    POSITIVE = 0x0000_0100,
    NEGATIVE = 0x0000_0200,
    ZERO = 0x0000_0400,
    UPPER_LIMIT = 0x0000_0800,
    LOWER_LIMIT = 0x0000_1000,
});

/// A required input parameter.
#[derive(Debug, Clone, Copy)]
pub struct InputInfo {
    pub param_name: &'static str,
    pub kind: InputType,
    pub flags: InputFlags,
}

/// An output parameter.
#[derive(Debug, Clone, Copy)]
pub struct OutputInfo {
    pub param_name: &'static str,
    pub kind: OutputType,
    pub flags: OutputFlags,
}

/// The domain of an optional input — type-safe replacement for C's `void* dataSet` + type tag.
#[derive(Debug, Clone, Copy)]
pub enum OptDomain {
    RealRange { min: f64, max: f64, precision: u8, default: f64, suggested: (f64, f64, f64) },
    IntegerRange { min: i32, max: i32, default: i32, suggested: (i32, i32, i32) },
    RealList { values: &'static [(f64, &'static str)], default: f64 },
    IntegerList { values: &'static [(i64, &'static str)], default: i64 },
}

/// An optional input parameter.
#[derive(Debug, Clone, Copy)]
pub struct OptInputInfo {
    pub param_name: &'static str,
    pub display_name: &'static str,
    pub hint: &'static str,
    pub flags: OptInputFlags,
    pub domain: OptDomain,
}

/// Metadata for one TA-Lib function (C: `TA_FuncInfo` + its parameter tables).
#[derive(Debug, Clone, Copy)]
pub struct FuncInfo {
    pub id: FuncId,
    pub name: &'static str,
    pub camel_case_name: &'static str,
    pub group: Group,
    pub hint: &'static str,
    pub flags: FuncFlags,
    pub inputs: &'static [InputInfo],
    pub opt_inputs: &'static [OptInputInfo],
    pub outputs: &'static [OutputInfo],
    /// Stable unstable-period id (the one metadata kept aligned to C); `None` if N/A.
    pub unst_id: Option<FuncUnstId>,
}

impl FuncInfo {
    #[inline] pub const fn nb_input(&self) -> usize { self.inputs.len() }
    #[inline] pub const fn nb_opt_input(&self) -> usize { self.opt_inputs.len() }
    #[inline] pub const fn nb_output(&self) -> usize { self.outputs.len() }
}

/// All function metadata, indexed by [`FuncId`]. Link-time const, in `.rodata`.
pub static FUNCS: [FuncInfo; 161] = [
    FuncInfo {
        id: FuncId::Accbands,
        name: "ACCBANDS",
        camel_case_name: "Accbands",
        group: Group::OverlapStudies,
        hint: "Acceleration Bands",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 20, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outRealUpperBand", kind: OutputType::Real, flags: OutputFlags(0x00000800) }, OutputInfo { param_name: "outRealMiddleBand", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outRealLowerBand", kind: OutputType::Real, flags: OutputFlags(0x00001000) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Acos,
        name: "ACOS",
        camel_case_name: "Acos",
        group: Group::MathTransform,
        hint: "Vector Trigonometric ACos",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Ad,
        name: "AD",
        camel_case_name: "Ad",
        group: Group::VolumeIndicators,
        hint: "Chaikin A/D Line",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLCV", kind: InputType::Price, flags: InputFlags(0x0000001e) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Add,
        name: "ADD",
        camel_case_name: "Add",
        group: Group::MathOperators,
        hint: "Vector Arithmetic Add",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal0", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inReal1", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Adosc,
        name: "ADOSC",
        camel_case_name: "AdOsc",
        group: Group::VolumeIndicators,
        hint: "Chaikin A/D Oscillator",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLCV", kind: InputType::Price, flags: InputFlags(0x0000001e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastPeriod", display_name: "Fast Period", hint: "Number of period for the fast MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 3, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInSlowPeriod", display_name: "Slow Period", hint: "Number of period for the slow MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 10, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Adx,
        name: "ADX",
        camel_case_name: "Adx",
        group: Group::MomentumIndicators,
        hint: "Average Directional Movement Index",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Adx),
    },
    FuncInfo {
        id: FuncId::Adxr,
        name: "ADXR",
        camel_case_name: "Adxr",
        group: Group::MomentumIndicators,
        hint: "Average Directional Movement Index Rating",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Adxr),
    },
    FuncInfo {
        id: FuncId::Apo,
        name: "APO",
        camel_case_name: "Apo",
        group: Group::MomentumIndicators,
        hint: "Absolute Price Oscillator",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastPeriod", display_name: "Fast Period", hint: "Number of period for the fast MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 12, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInSlowPeriod", display_name: "Slow Period", hint: "Number of period for the slow MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 26, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInMAType", display_name: "MA Type", hint: "Type of Moving Average", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Aroon,
        name: "AROON",
        camel_case_name: "Aroon",
        group: Group::MomentumIndicators,
        hint: "Aroon",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outAroonDown", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, OutputInfo { param_name: "outAroonUp", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Aroonosc,
        name: "AROONOSC",
        camel_case_name: "AroonOsc",
        group: Group::MomentumIndicators,
        hint: "Aroon Oscillator",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Asin,
        name: "ASIN",
        camel_case_name: "Asin",
        group: Group::MathTransform,
        hint: "Vector Trigonometric ASin",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Atan,
        name: "ATAN",
        camel_case_name: "Atan",
        group: Group::MathTransform,
        hint: "Vector Trigonometric ATan",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Atr,
        name: "ATR",
        camel_case_name: "Atr",
        group: Group::VolatilityIndicators,
        hint: "Average True Range",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 14, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Atr),
    },
    FuncInfo {
        id: FuncId::Avgdev,
        name: "AVGDEV",
        camel_case_name: "AvgDev",
        group: Group::PriceTransform,
        hint: "Average Deviation",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Avgprice,
        name: "AVGPRICE",
        camel_case_name: "AvgPrice",
        group: Group::PriceTransform,
        hint: "Average Price",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Bbands,
        name: "BBANDS",
        camel_case_name: "Bbands",
        group: Group::OverlapStudies,
        hint: "Bollinger Bands",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 5, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInNbDevUp", display_name: "Deviations up", hint: "Deviation multiplier for upper band", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: -3e37, max: 3e37, precision: 2, default: 2.0, suggested: (-2.0, 2.0, 0.2) } }, OptInputInfo { param_name: "optInNbDevDn", display_name: "Deviations down", hint: "Deviation multiplier for lower band", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: -3e37, max: 3e37, precision: 2, default: 2.0, suggested: (-2.0, 2.0, 0.2) } }, OptInputInfo { param_name: "optInMAType", display_name: "MA Type", hint: "Type of Moving Average", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outRealUpperBand", kind: OutputType::Real, flags: OutputFlags(0x00000800) }, OutputInfo { param_name: "outRealMiddleBand", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outRealLowerBand", kind: OutputType::Real, flags: OutputFlags(0x00001000) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Beta,
        name: "BETA",
        camel_case_name: "Beta",
        group: Group::StatisticFunctions,
        hint: "Beta",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal0", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inReal1", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 5, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Bop,
        name: "BOP",
        camel_case_name: "Bop",
        group: Group::MomentumIndicators,
        hint: "Balance Of Power",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cci,
        name: "CCI",
        camel_case_name: "Cci",
        group: Group::MomentumIndicators,
        hint: "Commodity Channel Index",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdl2crows,
        name: "CDL2CROWS",
        camel_case_name: "Cdl2Crows",
        group: Group::PatternRecognition,
        hint: "Two Crows",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdl3blackcrows,
        name: "CDL3BLACKCROWS",
        camel_case_name: "Cdl3BlackCrows",
        group: Group::PatternRecognition,
        hint: "Three Black Crows",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdl3inside,
        name: "CDL3INSIDE",
        camel_case_name: "Cdl3Inside",
        group: Group::PatternRecognition,
        hint: "Three Inside Up/Down",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdl3linestrike,
        name: "CDL3LINESTRIKE",
        camel_case_name: "Cdl3LineStrike",
        group: Group::PatternRecognition,
        hint: "Three-Line Strike ",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdl3outside,
        name: "CDL3OUTSIDE",
        camel_case_name: "Cdl3Outside",
        group: Group::PatternRecognition,
        hint: "Three Outside Up/Down",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdl3starsinsouth,
        name: "CDL3STARSINSOUTH",
        camel_case_name: "Cdl3StarsInSouth",
        group: Group::PatternRecognition,
        hint: "Three Stars In The South",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdl3whitesoldiers,
        name: "CDL3WHITESOLDIERS",
        camel_case_name: "Cdl3WhiteSoldiers",
        group: Group::PatternRecognition,
        hint: "Three Advancing White Soldiers",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlabandonedbaby,
        name: "CDLABANDONEDBABY",
        camel_case_name: "CdlAbandonedBaby",
        group: Group::PatternRecognition,
        hint: "Abandoned Baby",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInPenetration", display_name: "Penetration", hint: "Percentage of penetration of a candle within another candle", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 0, default: 0.3, suggested: (0.0, 0.0, 0.0) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdladvanceblock,
        name: "CDLADVANCEBLOCK",
        camel_case_name: "CdlAdvanceBlock",
        group: Group::PatternRecognition,
        hint: "Advance Block",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlbelthold,
        name: "CDLBELTHOLD",
        camel_case_name: "CdlBeltHold",
        group: Group::PatternRecognition,
        hint: "Belt-hold",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlbreakaway,
        name: "CDLBREAKAWAY",
        camel_case_name: "CdlBreakaway",
        group: Group::PatternRecognition,
        hint: "Breakaway",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlclosingmarubozu,
        name: "CDLCLOSINGMARUBOZU",
        camel_case_name: "CdlClosingMarubozu",
        group: Group::PatternRecognition,
        hint: "Closing Marubozu",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlconcealbabyswall,
        name: "CDLCONCEALBABYSWALL",
        camel_case_name: "CdlConcealBabysWall",
        group: Group::PatternRecognition,
        hint: "Concealing Baby Swallow",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlcounterattack,
        name: "CDLCOUNTERATTACK",
        camel_case_name: "CdlCounterAttack",
        group: Group::PatternRecognition,
        hint: "Counterattack",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdldarkcloudcover,
        name: "CDLDARKCLOUDCOVER",
        camel_case_name: "CdlDarkCloudCover",
        group: Group::PatternRecognition,
        hint: "Dark Cloud Cover",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInPenetration", display_name: "Penetration", hint: "Percentage of penetration of a candle within another candle", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 0, default: 0.5, suggested: (0.0, 0.0, 0.0) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdldoji,
        name: "CDLDOJI",
        camel_case_name: "CdlDoji",
        group: Group::PatternRecognition,
        hint: "Doji",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdldojistar,
        name: "CDLDOJISTAR",
        camel_case_name: "CdlDojiStar",
        group: Group::PatternRecognition,
        hint: "Doji Star",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdldragonflydoji,
        name: "CDLDRAGONFLYDOJI",
        camel_case_name: "CdlDragonflyDoji",
        group: Group::PatternRecognition,
        hint: "Dragonfly Doji",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlengulfing,
        name: "CDLENGULFING",
        camel_case_name: "CdlEngulfing",
        group: Group::PatternRecognition,
        hint: "Engulfing Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdleveningdojistar,
        name: "CDLEVENINGDOJISTAR",
        camel_case_name: "CdlEveningDojiStar",
        group: Group::PatternRecognition,
        hint: "Evening Doji Star",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInPenetration", display_name: "Penetration", hint: "Percentage of penetration of a candle within another candle", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 0, default: 0.3, suggested: (0.0, 0.0, 0.0) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdleveningstar,
        name: "CDLEVENINGSTAR",
        camel_case_name: "CdlEveningStar",
        group: Group::PatternRecognition,
        hint: "Evening Star",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInPenetration", display_name: "Penetration", hint: "Percentage of penetration of a candle within another candle", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 0, default: 0.3, suggested: (0.0, 0.0, 0.0) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlgapsidesidewhite,
        name: "CDLGAPSIDESIDEWHITE",
        camel_case_name: "CdlGapSideSideWhite",
        group: Group::PatternRecognition,
        hint: "Up/Down-gap side-by-side white lines",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlgravestonedoji,
        name: "CDLGRAVESTONEDOJI",
        camel_case_name: "CdlGravestoneDoji",
        group: Group::PatternRecognition,
        hint: "Gravestone Doji",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlhammer,
        name: "CDLHAMMER",
        camel_case_name: "CdlHammer",
        group: Group::PatternRecognition,
        hint: "Hammer",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlhangingman,
        name: "CDLHANGINGMAN",
        camel_case_name: "CdlHangingMan",
        group: Group::PatternRecognition,
        hint: "Hanging Man",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlharami,
        name: "CDLHARAMI",
        camel_case_name: "CdlHarami",
        group: Group::PatternRecognition,
        hint: "Harami Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlharamicross,
        name: "CDLHARAMICROSS",
        camel_case_name: "CdlHaramiCross",
        group: Group::PatternRecognition,
        hint: "Harami Cross Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlhighwave,
        name: "CDLHIGHWAVE",
        camel_case_name: "CdlHignWave",
        group: Group::PatternRecognition,
        hint: "High-Wave Candle",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlhikkake,
        name: "CDLHIKKAKE",
        camel_case_name: "CdlHikkake",
        group: Group::PatternRecognition,
        hint: "Hikkake Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlhikkakemod,
        name: "CDLHIKKAKEMOD",
        camel_case_name: "CdlHikkakeMod",
        group: Group::PatternRecognition,
        hint: "Modified Hikkake Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlhomingpigeon,
        name: "CDLHOMINGPIGEON",
        camel_case_name: "CdlHomingPigeon",
        group: Group::PatternRecognition,
        hint: "Homing Pigeon",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlidentical3crows,
        name: "CDLIDENTICAL3CROWS",
        camel_case_name: "CdlIdentical3Crows",
        group: Group::PatternRecognition,
        hint: "Identical Three Crows",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlinneck,
        name: "CDLINNECK",
        camel_case_name: "CdlInNeck",
        group: Group::PatternRecognition,
        hint: "In-Neck Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlinvertedhammer,
        name: "CDLINVERTEDHAMMER",
        camel_case_name: "CdlInvertedHammer",
        group: Group::PatternRecognition,
        hint: "Inverted Hammer",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlkicking,
        name: "CDLKICKING",
        camel_case_name: "CdlKicking",
        group: Group::PatternRecognition,
        hint: "Kicking",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlkickingbylength,
        name: "CDLKICKINGBYLENGTH",
        camel_case_name: "CdlKickingByLength",
        group: Group::PatternRecognition,
        hint: "Kicking - bull/bear determined by the longer marubozu",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlladderbottom,
        name: "CDLLADDERBOTTOM",
        camel_case_name: "CdlLadderBottom",
        group: Group::PatternRecognition,
        hint: "Ladder Bottom",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdllongleggeddoji,
        name: "CDLLONGLEGGEDDOJI",
        camel_case_name: "CdlLongLeggedDoji",
        group: Group::PatternRecognition,
        hint: "Long Legged Doji",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdllongline,
        name: "CDLLONGLINE",
        camel_case_name: "CdlLongLine",
        group: Group::PatternRecognition,
        hint: "Long Line Candle",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlmarubozu,
        name: "CDLMARUBOZU",
        camel_case_name: "CdlMarubozu",
        group: Group::PatternRecognition,
        hint: "Marubozu",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlmatchinglow,
        name: "CDLMATCHINGLOW",
        camel_case_name: "CdlMatchingLow",
        group: Group::PatternRecognition,
        hint: "Matching Low",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlmathold,
        name: "CDLMATHOLD",
        camel_case_name: "CdlMatHold",
        group: Group::PatternRecognition,
        hint: "Mat Hold",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInPenetration", display_name: "Penetration", hint: "Percentage of penetration of a candle within another candle", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 0, default: 0.5, suggested: (0.0, 0.0, 0.0) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlmorningdojistar,
        name: "CDLMORNINGDOJISTAR",
        camel_case_name: "CdlMorningDojiStar",
        group: Group::PatternRecognition,
        hint: "Morning Doji Star",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInPenetration", display_name: "Penetration", hint: "Percentage of penetration of a candle within another candle", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 0, default: 0.3, suggested: (0.0, 0.0, 0.0) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlmorningstar,
        name: "CDLMORNINGSTAR",
        camel_case_name: "CdlMorningStar",
        group: Group::PatternRecognition,
        hint: "Morning Star",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInPenetration", display_name: "Penetration", hint: "Percentage of penetration of a candle within another candle", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 0, default: 0.3, suggested: (0.0, 0.0, 0.0) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlonneck,
        name: "CDLONNECK",
        camel_case_name: "CdlOnNeck",
        group: Group::PatternRecognition,
        hint: "On-Neck Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlpiercing,
        name: "CDLPIERCING",
        camel_case_name: "CdlPiercing",
        group: Group::PatternRecognition,
        hint: "Piercing Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlrickshawman,
        name: "CDLRICKSHAWMAN",
        camel_case_name: "CdlRickshawMan",
        group: Group::PatternRecognition,
        hint: "Rickshaw Man",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlrisefall3methods,
        name: "CDLRISEFALL3METHODS",
        camel_case_name: "CdlRiseFall3Methods",
        group: Group::PatternRecognition,
        hint: "Rising/Falling Three Methods",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlseparatinglines,
        name: "CDLSEPARATINGLINES",
        camel_case_name: "CdlSeperatingLines",
        group: Group::PatternRecognition,
        hint: "Separating Lines",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlshootingstar,
        name: "CDLSHOOTINGSTAR",
        camel_case_name: "CdlShootingStar",
        group: Group::PatternRecognition,
        hint: "Shooting Star",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlshortline,
        name: "CDLSHORTLINE",
        camel_case_name: "CdlShortLine",
        group: Group::PatternRecognition,
        hint: "Short Line Candle",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlspinningtop,
        name: "CDLSPINNINGTOP",
        camel_case_name: "CdlSpinningTop",
        group: Group::PatternRecognition,
        hint: "Spinning Top",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlstalledpattern,
        name: "CDLSTALLEDPATTERN",
        camel_case_name: "CdlStalledPattern",
        group: Group::PatternRecognition,
        hint: "Stalled Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlsticksandwich,
        name: "CDLSTICKSANDWICH",
        camel_case_name: "CdlStickSandwich",
        group: Group::PatternRecognition,
        hint: "Stick Sandwich",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdltakuri,
        name: "CDLTAKURI",
        camel_case_name: "CdlTakuri",
        group: Group::PatternRecognition,
        hint: "Takuri (Dragonfly Doji with very long lower shadow)",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdltasukigap,
        name: "CDLTASUKIGAP",
        camel_case_name: "CdlTasukiGap",
        group: Group::PatternRecognition,
        hint: "Tasuki Gap",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlthrusting,
        name: "CDLTHRUSTING",
        camel_case_name: "CdlThrusting",
        group: Group::PatternRecognition,
        hint: "Thrusting Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdltristar,
        name: "CDLTRISTAR",
        camel_case_name: "CdlTristar",
        group: Group::PatternRecognition,
        hint: "Tristar Pattern",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlunique3river,
        name: "CDLUNIQUE3RIVER",
        camel_case_name: "CdlUnique3River",
        group: Group::PatternRecognition,
        hint: "Unique 3 River",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlupsidegap2crows,
        name: "CDLUPSIDEGAP2CROWS",
        camel_case_name: "CdlUpsideGap2Crows",
        group: Group::PatternRecognition,
        hint: "Upside Gap Two Crows",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cdlxsidegap3methods,
        name: "CDLXSIDEGAP3METHODS",
        camel_case_name: "CdlXSideGap3Methods",
        group: Group::PatternRecognition,
        hint: "Upside/Downside Gap Three Methods",
        flags: FuncFlags(0x10000000),
        inputs: &[InputInfo { param_name: "inPriceOHLC", kind: InputType::Price, flags: InputFlags(0x0000000f) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Ceil,
        name: "CEIL",
        camel_case_name: "Ceil",
        group: Group::MathTransform,
        hint: "Vector Ceil",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cmo,
        name: "CMO",
        camel_case_name: "Cmo",
        group: Group::MomentumIndicators,
        hint: "Chande Momentum Oscillator",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Cmo),
    },
    FuncInfo {
        id: FuncId::Correl,
        name: "CORREL",
        camel_case_name: "Correl",
        group: Group::StatisticFunctions,
        hint: "Pearson's Correlation Coefficient (r)",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal0", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inReal1", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cos,
        name: "COS",
        camel_case_name: "Cos",
        group: Group::MathTransform,
        hint: "Vector Trigonometric Cos",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Cosh,
        name: "COSH",
        camel_case_name: "Cosh",
        group: Group::MathTransform,
        hint: "Vector Trigonometric Cosh",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Dema,
        name: "DEMA",
        camel_case_name: "Dema",
        group: Group::OverlapStudies,
        hint: "Double Exponential Moving Average",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Div,
        name: "DIV",
        camel_case_name: "Div",
        group: Group::MathOperators,
        hint: "Vector Arithmetic Div",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal0", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inReal1", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Dx,
        name: "DX",
        camel_case_name: "Dx",
        group: Group::MomentumIndicators,
        hint: "Directional Movement Index",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Dx),
    },
    FuncInfo {
        id: FuncId::Ema,
        name: "EMA",
        camel_case_name: "Ema",
        group: Group::OverlapStudies,
        hint: "Exponential Moving Average",
        flags: FuncFlags(0x09000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Ema),
    },
    FuncInfo {
        id: FuncId::Exp,
        name: "EXP",
        camel_case_name: "Exp",
        group: Group::MathTransform,
        hint: "Vector Arithmetic Exp",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Floor,
        name: "FLOOR",
        camel_case_name: "Floor",
        group: Group::MathTransform,
        hint: "Vector Floor",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::HtDcperiod,
        name: "HT_DCPERIOD",
        camel_case_name: "HtDcPeriod",
        group: Group::CycleIndicators,
        hint: "Hilbert Transform - Dominant Cycle Period",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::HtDcPeriod),
    },
    FuncInfo {
        id: FuncId::HtDcphase,
        name: "HT_DCPHASE",
        camel_case_name: "HtDcPhase",
        group: Group::CycleIndicators,
        hint: "Hilbert Transform - Dominant Cycle Phase",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::HtDcPhase),
    },
    FuncInfo {
        id: FuncId::HtPhasor,
        name: "HT_PHASOR",
        camel_case_name: "HtPhasor",
        group: Group::CycleIndicators,
        hint: "Hilbert Transform - Phasor Components",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInPhase", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outQuadrature", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, ],
        unst_id: Some(FuncUnstId::HtPhasor),
    },
    FuncInfo {
        id: FuncId::HtSine,
        name: "HT_SINE",
        camel_case_name: "HtSine",
        group: Group::CycleIndicators,
        hint: "Hilbert Transform - SineWave",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outSine", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outLeadSine", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, ],
        unst_id: Some(FuncUnstId::HtSine),
    },
    FuncInfo {
        id: FuncId::HtTrendline,
        name: "HT_TRENDLINE",
        camel_case_name: "HtTrendline",
        group: Group::OverlapStudies,
        hint: "Hilbert Transform - Instantaneous Trendline",
        flags: FuncFlags(0x09000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::HtTrendline),
    },
    FuncInfo {
        id: FuncId::HtTrendmode,
        name: "HT_TRENDMODE",
        camel_case_name: "HtTrendMode",
        group: Group::CycleIndicators,
        hint: "Hilbert Transform - Trend vs Cycle Mode",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::HtTrendMode),
    },
    FuncInfo {
        id: FuncId::Imi,
        name: "IMI",
        camel_case_name: "Imi",
        group: Group::MomentumIndicators,
        hint: "Intraday Momentum Index",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceOC", kind: InputType::Price, flags: InputFlags(0x00000009) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Imi),
    },
    FuncInfo {
        id: FuncId::Kama,
        name: "KAMA",
        camel_case_name: "Kama",
        group: Group::OverlapStudies,
        hint: "Kaufman Adaptive Moving Average",
        flags: FuncFlags(0x09000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Kama),
    },
    FuncInfo {
        id: FuncId::Linearreg,
        name: "LINEARREG",
        camel_case_name: "LinearReg",
        group: Group::StatisticFunctions,
        hint: "Linear Regression",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::LinearregAngle,
        name: "LINEARREG_ANGLE",
        camel_case_name: "LinearRegAngle",
        group: Group::StatisticFunctions,
        hint: "Linear Regression Angle",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::LinearregIntercept,
        name: "LINEARREG_INTERCEPT",
        camel_case_name: "LinearRegIntercept",
        group: Group::StatisticFunctions,
        hint: "Linear Regression Intercept",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::LinearregSlope,
        name: "LINEARREG_SLOPE",
        camel_case_name: "LinearRegSlope",
        group: Group::StatisticFunctions,
        hint: "Linear Regression Slope",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Ln,
        name: "LN",
        camel_case_name: "Ln",
        group: Group::MathTransform,
        hint: "Vector Log Natural",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Log10,
        name: "LOG10",
        camel_case_name: "Log10",
        group: Group::MathTransform,
        hint: "Vector Log10",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Ma,
        name: "MA",
        camel_case_name: "MovingAverage",
        group: Group::OverlapStudies,
        hint: "Moving average",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInMAType", display_name: "MA Type", hint: "Type of Moving Average", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Macd,
        name: "MACD",
        camel_case_name: "Macd",
        group: Group::MomentumIndicators,
        hint: "Moving Average Convergence/Divergence",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastPeriod", display_name: "Fast Period", hint: "Number of period for the fast MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 12, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInSlowPeriod", display_name: "Slow Period", hint: "Number of period for the slow MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 26, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInSignalPeriod", display_name: "Signal Period", hint: "Smoothing for the signal line (nb of period)", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 9, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outMACD", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outMACDSignal", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, OutputInfo { param_name: "outMACDHist", kind: OutputType::Real, flags: OutputFlags(0x00000010) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Macdext,
        name: "MACDEXT",
        camel_case_name: "MacdExt",
        group: Group::MomentumIndicators,
        hint: "MACD with controllable MA type",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastPeriod", display_name: "Fast Period", hint: "Number of period for the fast MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 12, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInFastMAType", display_name: "Fast MA", hint: "Type of Moving Average for fast MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, OptInputInfo { param_name: "optInSlowPeriod", display_name: "Slow Period", hint: "Number of period for the slow MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 26, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInSlowMAType", display_name: "Slow MA", hint: "Type of Moving Average for slow MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, OptInputInfo { param_name: "optInSignalPeriod", display_name: "Signal Period", hint: "Smoothing for the signal line (nb of period)", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 9, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInSignalMAType", display_name: "Signal MA", hint: "Type of Moving Average for signal line", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outMACD", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outMACDSignal", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, OutputInfo { param_name: "outMACDHist", kind: OutputType::Real, flags: OutputFlags(0x00000010) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Macdfix,
        name: "MACDFIX",
        camel_case_name: "MacdFix",
        group: Group::MomentumIndicators,
        hint: "Moving Average Convergence/Divergence Fix 12/26",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInSignalPeriod", display_name: "Signal Period", hint: "Smoothing for the signal line (nb of period)", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 9, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outMACD", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outMACDSignal", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, OutputInfo { param_name: "outMACDHist", kind: OutputType::Real, flags: OutputFlags(0x00000010) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Mama,
        name: "MAMA",
        camel_case_name: "Mama",
        group: Group::OverlapStudies,
        hint: "MESA Adaptive Moving Average",
        flags: FuncFlags(0x09000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastLimit", display_name: "Fast Limit", hint: "Upper limit use in the adaptive algorithm", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.01, max: 0.99, precision: 2, default: 0.5, suggested: (0.21, 0.8, 0.01) } }, OptInputInfo { param_name: "optInSlowLimit", display_name: "Slow Limit", hint: "Lower limit use in the adaptive algorithm", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.01, max: 0.99, precision: 2, default: 0.05, suggested: (0.01, 0.6, 0.01) } }, ],
        outputs: &[OutputInfo { param_name: "outMAMA", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outFAMA", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, ],
        unst_id: Some(FuncUnstId::Mama),
    },
    FuncInfo {
        id: FuncId::Mavp,
        name: "MAVP",
        camel_case_name: "MovingAverageVariablePeriod",
        group: Group::OverlapStudies,
        hint: "Moving average with variable period",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inPeriods", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInMinPeriod", display_name: "Minimum Period", hint: "Value less than minimum will be changed to Minimum period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 2, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInMaxPeriod", display_name: "Maximum Period", hint: "Value higher than maximum will be changed to Maximum period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInMAType", display_name: "MA Type", hint: "Type of Moving Average", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Max,
        name: "MAX",
        camel_case_name: "Max",
        group: Group::MathOperators,
        hint: "Highest value over a specified period",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 30, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Maxindex,
        name: "MAXINDEX",
        camel_case_name: "MaxIndex",
        group: Group::MathOperators,
        hint: "Index of highest value over a specified period",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 30, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Medprice,
        name: "MEDPRICE",
        camel_case_name: "MedPrice",
        group: Group::PriceTransform,
        hint: "Median Price",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Mfi,
        name: "MFI",
        camel_case_name: "Mfi",
        group: Group::MomentumIndicators,
        hint: "Money Flow Index",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLCV", kind: InputType::Price, flags: InputFlags(0x0000001e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Mfi),
    },
    FuncInfo {
        id: FuncId::Midpoint,
        name: "MIDPOINT",
        camel_case_name: "MidPoint",
        group: Group::OverlapStudies,
        hint: "MidPoint over period",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Midprice,
        name: "MIDPRICE",
        camel_case_name: "MidPrice",
        group: Group::OverlapStudies,
        hint: "Midpoint Price over period",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Min,
        name: "MIN",
        camel_case_name: "Min",
        group: Group::MathOperators,
        hint: "Lowest value over a specified period",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 30, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Minindex,
        name: "MININDEX",
        camel_case_name: "MinIndex",
        group: Group::MathOperators,
        hint: "Index of lowest value over a specified period",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 30, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outInteger", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Minmax,
        name: "MINMAX",
        camel_case_name: "MinMax",
        group: Group::MathOperators,
        hint: "Lowest and highest values over a specified period",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 30, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outMin", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outMax", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Minmaxindex,
        name: "MINMAXINDEX",
        camel_case_name: "MinMaxIndex",
        group: Group::MathOperators,
        hint: "Indexes of lowest and highest values over a specified period",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 30, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outMinIdx", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outMaxIdx", kind: OutputType::Integer, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::MinusDi,
        name: "MINUS_DI",
        camel_case_name: "MinusDI",
        group: Group::MomentumIndicators,
        hint: "Minus Directional Indicator",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 14, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::MinusDI),
    },
    FuncInfo {
        id: FuncId::MinusDm,
        name: "MINUS_DM",
        camel_case_name: "MinusDM",
        group: Group::MomentumIndicators,
        hint: "Minus Directional Movement",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 14, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::MinusDM),
    },
    FuncInfo {
        id: FuncId::Mom,
        name: "MOM",
        camel_case_name: "Mom",
        group: Group::MomentumIndicators,
        hint: "Momentum",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 10, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Mult,
        name: "MULT",
        camel_case_name: "Mult",
        group: Group::MathOperators,
        hint: "Vector Arithmetic Mult",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal0", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inReal1", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Natr,
        name: "NATR",
        camel_case_name: "Natr",
        group: Group::VolatilityIndicators,
        hint: "Normalized Average True Range",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 14, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Natr),
    },
    FuncInfo {
        id: FuncId::Obv,
        name: "OBV",
        camel_case_name: "Obv",
        group: Group::VolumeIndicators,
        hint: "On Balance Volume",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inPriceV", kind: InputType::Price, flags: InputFlags(0x00000010) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::PlusDi,
        name: "PLUS_DI",
        camel_case_name: "PlusDI",
        group: Group::MomentumIndicators,
        hint: "Plus Directional Indicator",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 14, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::PlusDI),
    },
    FuncInfo {
        id: FuncId::PlusDm,
        name: "PLUS_DM",
        camel_case_name: "PlusDM",
        group: Group::MomentumIndicators,
        hint: "Plus Directional Movement",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 14, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::PlusDM),
    },
    FuncInfo {
        id: FuncId::Ppo,
        name: "PPO",
        camel_case_name: "Ppo",
        group: Group::MomentumIndicators,
        hint: "Percentage Price Oscillator",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastPeriod", display_name: "Fast Period", hint: "Number of period for the fast MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 12, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInSlowPeriod", display_name: "Slow Period", hint: "Number of period for the slow MA", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 26, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInMAType", display_name: "MA Type", hint: "Type of Moving Average", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Roc,
        name: "ROC",
        camel_case_name: "Roc",
        group: Group::MomentumIndicators,
        hint: "Rate of change : ((price/prevPrice)-1)*100",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 10, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Rocp,
        name: "ROCP",
        camel_case_name: "RocP",
        group: Group::MomentumIndicators,
        hint: "Rate of change Percentage: (price-prevPrice)/prevPrice",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 10, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Rocr,
        name: "ROCR",
        camel_case_name: "RocR",
        group: Group::MomentumIndicators,
        hint: "Rate of change ratio: (price/prevPrice)",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 10, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Rocr100,
        name: "ROCR100",
        camel_case_name: "RocR100",
        group: Group::MomentumIndicators,
        hint: "Rate of change ratio 100 scale: (price/prevPrice)*100",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 10, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Rsi,
        name: "RSI",
        camel_case_name: "Rsi",
        group: Group::MomentumIndicators,
        hint: "Relative Strength Index",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::Rsi),
    },
    FuncInfo {
        id: FuncId::Sar,
        name: "SAR",
        camel_case_name: "Sar",
        group: Group::OverlapStudies,
        hint: "Parabolic SAR",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInAcceleration", display_name: "Acceleration Factor", hint: "Acceleration Factor used up to the Maximum value", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.02, suggested: (0.01, 0.2, 0.01) } }, OptInputInfo { param_name: "optInMaximum", display_name: "AF Maximum", hint: "Acceleration Factor Maximum value", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.2, suggested: (0.2, 0.4, 0.01) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Sarext,
        name: "SAREXT",
        camel_case_name: "SarExt",
        group: Group::OverlapStudies,
        hint: "Parabolic SAR - Extended",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceHL", kind: InputType::Price, flags: InputFlags(0x00000006) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInStartValue", display_name: "Start Value", hint: "Start value and direction. 0 for Auto, >0 for Long, <0 for Short", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: -3e37, max: 3e37, precision: 4, default: 0.0, suggested: (0.0, 0.0, 0.0) } }, OptInputInfo { param_name: "optInOffsetOnReverse", display_name: "Offset on Reverse", hint: "Percent offset added/removed to initial stop on short/long reversal", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.0, suggested: (0.01, 0.15, 0.01) } }, OptInputInfo { param_name: "optInAccelerationInitLong", display_name: "AF Init Long", hint: "Acceleration Factor initial value for the Long direction", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.02, suggested: (0.01, 0.19, 0.01) } }, OptInputInfo { param_name: "optInAccelerationLong", display_name: "AF Long", hint: "Acceleration Factor for the Long direction", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.02, suggested: (0.01, 0.2, 0.01) } }, OptInputInfo { param_name: "optInAccelerationMaxLong", display_name: "AF Max Long", hint: "Acceleration Factor maximum value for the Long direction", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.2, suggested: (0.2, 0.4, 0.01) } }, OptInputInfo { param_name: "optInAccelerationInitShort", display_name: "AF Init Short", hint: "Acceleration Factor initial value for the Short direction", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.02, suggested: (0.01, 0.19, 0.01) } }, OptInputInfo { param_name: "optInAccelerationShort", display_name: "AF Short", hint: "Acceleration Factor for the Short direction", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.02, suggested: (0.01, 0.2, 0.01) } }, OptInputInfo { param_name: "optInAccelerationMaxShort", display_name: "AF Max Short", hint: "Acceleration Factor maximum value for the Short direction", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 3e37, precision: 4, default: 0.2, suggested: (0.2, 0.4, 0.01) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Sin,
        name: "SIN",
        camel_case_name: "Sin",
        group: Group::MathTransform,
        hint: "Vector Trigonometric Sin",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Sinh,
        name: "SINH",
        camel_case_name: "Sinh",
        group: Group::MathTransform,
        hint: "Vector Trigonometric Sinh",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Sma,
        name: "SMA",
        camel_case_name: "Sma",
        group: Group::OverlapStudies,
        hint: "Simple Moving Average",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Sqrt,
        name: "SQRT",
        camel_case_name: "Sqrt",
        group: Group::MathTransform,
        hint: "Vector Square Root",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Stddev,
        name: "STDDEV",
        camel_case_name: "StdDev",
        group: Group::StatisticFunctions,
        hint: "Standard Deviation",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 5, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInNbDev", display_name: "Deviations", hint: "Nb of deviations", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: -3e37, max: 3e37, precision: 2, default: 1.0, suggested: (-2.0, 2.0, 0.2) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Stoch,
        name: "STOCH",
        camel_case_name: "Stoch",
        group: Group::MomentumIndicators,
        hint: "Stochastic",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastK_Period", display_name: "Fast-K Period", hint: "Time period for building the Fast-K line", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 5, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInSlowK_Period", display_name: "Slow-K Period", hint: "Smoothing for making the Slow-K line. Usually set to 3", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 3, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInSlowK_MAType", display_name: "Slow-K MA", hint: "Type of Moving Average for Slow-K", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, OptInputInfo { param_name: "optInSlowD_Period", display_name: "Slow-D Period", hint: "Smoothing for making the Slow-D line", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 3, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInSlowD_MAType", display_name: "Slow-D MA", hint: "Type of Moving Average for Slow-D", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outSlowK", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, OutputInfo { param_name: "outSlowD", kind: OutputType::Real, flags: OutputFlags(0x00000004) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Stochf,
        name: "STOCHF",
        camel_case_name: "StochF",
        group: Group::MomentumIndicators,
        hint: "Stochastic Fast",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInFastK_Period", display_name: "Fast-K Period", hint: "Time period for building the Fast-K line", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 5, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInFastD_Period", display_name: "Fast-D Period", hint: "Smoothing for making the Fast-D line. Usually set to 3", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 3, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInFastD_MAType", display_name: "Fast-D MA", hint: "Type of Moving Average for Fast-D", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outFastK", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outFastD", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Stochrsi,
        name: "STOCHRSI",
        camel_case_name: "StochRsi",
        group: Group::MomentumIndicators,
        hint: "Stochastic Relative Strength Index",
        flags: FuncFlags(0x08000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, OptInputInfo { param_name: "optInFastK_Period", display_name: "Fast-K Period", hint: "Time period for building the Fast-K line", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 5, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInFastD_Period", display_name: "Fast-D Period", hint: "Smoothing for making the Fast-D line. Usually set to 3", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 3, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInFastD_MAType", display_name: "Fast-D MA", hint: "Type of Moving Average for Fast-D", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerList { values: &[(0, "SMA"), (1, "EMA"), (2, "WMA"), (3, "DEMA"), (4, "TEMA"), (5, "TRIMA"), (6, "KAMA"), (7, "MAMA"), (8, "T3"), ], default: 0 } }, ],
        outputs: &[OutputInfo { param_name: "outFastK", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, OutputInfo { param_name: "outFastD", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::StochRsi),
    },
    FuncInfo {
        id: FuncId::Sub,
        name: "SUB",
        camel_case_name: "Sub",
        group: Group::MathOperators,
        hint: "Vector Arithmetic Subtraction",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal0", kind: InputType::Real, flags: InputFlags(0) }, InputInfo { param_name: "inReal1", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Sum,
        name: "SUM",
        camel_case_name: "Sum",
        group: Group::MathOperators,
        hint: "Summation",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 30, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::T3,
        name: "T3",
        camel_case_name: "T3",
        group: Group::OverlapStudies,
        hint: "Triple Exponential Moving Average (T3)",
        flags: FuncFlags(0x09000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 5, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInVFactor", display_name: "Volume Factor", hint: "Volume Factor", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: 0.0, max: 1.0, precision: 2, default: 0.7, suggested: (0.01, 1.0, 0.05) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: Some(FuncUnstId::T3),
    },
    FuncInfo {
        id: FuncId::Tan,
        name: "TAN",
        camel_case_name: "Tan",
        group: Group::MathTransform,
        hint: "Vector Trigonometric Tan",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Tanh,
        name: "TANH",
        camel_case_name: "Tanh",
        group: Group::MathTransform,
        hint: "Vector Trigonometric Tanh",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Tema,
        name: "TEMA",
        camel_case_name: "Tema",
        group: Group::OverlapStudies,
        hint: "Triple Exponential Moving Average",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Trange,
        name: "TRANGE",
        camel_case_name: "TrueRange",
        group: Group::VolatilityIndicators,
        hint: "True Range",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Trima,
        name: "TRIMA",
        camel_case_name: "Trima",
        group: Group::OverlapStudies,
        hint: "Triangular Moving Average",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Trix,
        name: "TRIX",
        camel_case_name: "Trix",
        group: Group::MomentumIndicators,
        hint: "1-day Rate-Of-Change (ROC) of a Triple Smooth EMA",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Tsf,
        name: "TSF",
        camel_case_name: "Tsf",
        group: Group::StatisticFunctions,
        hint: "Time Series Forecast",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Typprice,
        name: "TYPPRICE",
        camel_case_name: "TypPrice",
        group: Group::PriceTransform,
        hint: "Typical Price",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Ultosc,
        name: "ULTOSC",
        camel_case_name: "UltOsc",
        group: Group::MomentumIndicators,
        hint: "Ultimate Oscillator",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod1", display_name: "First Period", hint: "Number of bars for 1st period.", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 7, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInTimePeriod2", display_name: "Second Period", hint: "Number of bars fro 2nd period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 14, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInTimePeriod3", display_name: "Third Period", hint: "Number of bars for 3rd period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 28, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Var,
        name: "VAR",
        camel_case_name: "Variance",
        group: Group::StatisticFunctions,
        hint: "Variance",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 5, suggested: (1, 200, 1) } }, OptInputInfo { param_name: "optInNbDev", display_name: "Deviations", hint: "Nb of deviations", flags: OptInputFlags(0x00000000), domain: OptDomain::RealRange { min: -3e37, max: 3e37, precision: 2, default: 1.0, suggested: (-2.0, 2.0, 0.2) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Wclprice,
        name: "WCLPRICE",
        camel_case_name: "WclPrice",
        group: Group::PriceTransform,
        hint: "Weighted Close Price",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Willr,
        name: "WILLR",
        camel_case_name: "WillR",
        group: Group::MomentumIndicators,
        hint: "Williams' %R",
        flags: FuncFlags(0x00000000),
        inputs: &[InputInfo { param_name: "inPriceHLC", kind: InputType::Price, flags: InputFlags(0x0000000e) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 2, max: 100000, default: 14, suggested: (4, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
    FuncInfo {
        id: FuncId::Wma,
        name: "WMA",
        camel_case_name: "Wma",
        group: Group::OverlapStudies,
        hint: "Weighted Moving Average",
        flags: FuncFlags(0x01000000),
        inputs: &[InputInfo { param_name: "inReal", kind: InputType::Real, flags: InputFlags(0) }, ],
        opt_inputs: &[OptInputInfo { param_name: "optInTimePeriod", display_name: "Time Period", hint: "Number of period", flags: OptInputFlags(0x00000000), domain: OptDomain::IntegerRange { min: 1, max: 100000, default: 30, suggested: (1, 200, 1) } }, ],
        outputs: &[OutputInfo { param_name: "outReal", kind: OutputType::Real, flags: OutputFlags(0x00000001) }, ],
        unst_id: None,
    },
];

/// Resolve a function name (e.g. "RSI") to its [`FuncId`].
///
/// Uses a generated `match` — see the module-level docs for why this is O(1)
/// and faster than C's linear `strcmp` scan, with zero allocation/dependencies.
pub fn get_func_handle(name: &str) -> Option<FuncId> {
    Some(match name {
        "ACCBANDS" => FuncId::Accbands,
        "ACOS" => FuncId::Acos,
        "AD" => FuncId::Ad,
        "ADD" => FuncId::Add,
        "ADOSC" => FuncId::Adosc,
        "ADX" => FuncId::Adx,
        "ADXR" => FuncId::Adxr,
        "APO" => FuncId::Apo,
        "AROON" => FuncId::Aroon,
        "AROONOSC" => FuncId::Aroonosc,
        "ASIN" => FuncId::Asin,
        "ATAN" => FuncId::Atan,
        "ATR" => FuncId::Atr,
        "AVGDEV" => FuncId::Avgdev,
        "AVGPRICE" => FuncId::Avgprice,
        "BBANDS" => FuncId::Bbands,
        "BETA" => FuncId::Beta,
        "BOP" => FuncId::Bop,
        "CCI" => FuncId::Cci,
        "CDL2CROWS" => FuncId::Cdl2crows,
        "CDL3BLACKCROWS" => FuncId::Cdl3blackcrows,
        "CDL3INSIDE" => FuncId::Cdl3inside,
        "CDL3LINESTRIKE" => FuncId::Cdl3linestrike,
        "CDL3OUTSIDE" => FuncId::Cdl3outside,
        "CDL3STARSINSOUTH" => FuncId::Cdl3starsinsouth,
        "CDL3WHITESOLDIERS" => FuncId::Cdl3whitesoldiers,
        "CDLABANDONEDBABY" => FuncId::Cdlabandonedbaby,
        "CDLADVANCEBLOCK" => FuncId::Cdladvanceblock,
        "CDLBELTHOLD" => FuncId::Cdlbelthold,
        "CDLBREAKAWAY" => FuncId::Cdlbreakaway,
        "CDLCLOSINGMARUBOZU" => FuncId::Cdlclosingmarubozu,
        "CDLCONCEALBABYSWALL" => FuncId::Cdlconcealbabyswall,
        "CDLCOUNTERATTACK" => FuncId::Cdlcounterattack,
        "CDLDARKCLOUDCOVER" => FuncId::Cdldarkcloudcover,
        "CDLDOJI" => FuncId::Cdldoji,
        "CDLDOJISTAR" => FuncId::Cdldojistar,
        "CDLDRAGONFLYDOJI" => FuncId::Cdldragonflydoji,
        "CDLENGULFING" => FuncId::Cdlengulfing,
        "CDLEVENINGDOJISTAR" => FuncId::Cdleveningdojistar,
        "CDLEVENINGSTAR" => FuncId::Cdleveningstar,
        "CDLGAPSIDESIDEWHITE" => FuncId::Cdlgapsidesidewhite,
        "CDLGRAVESTONEDOJI" => FuncId::Cdlgravestonedoji,
        "CDLHAMMER" => FuncId::Cdlhammer,
        "CDLHANGINGMAN" => FuncId::Cdlhangingman,
        "CDLHARAMI" => FuncId::Cdlharami,
        "CDLHARAMICROSS" => FuncId::Cdlharamicross,
        "CDLHIGHWAVE" => FuncId::Cdlhighwave,
        "CDLHIKKAKE" => FuncId::Cdlhikkake,
        "CDLHIKKAKEMOD" => FuncId::Cdlhikkakemod,
        "CDLHOMINGPIGEON" => FuncId::Cdlhomingpigeon,
        "CDLIDENTICAL3CROWS" => FuncId::Cdlidentical3crows,
        "CDLINNECK" => FuncId::Cdlinneck,
        "CDLINVERTEDHAMMER" => FuncId::Cdlinvertedhammer,
        "CDLKICKING" => FuncId::Cdlkicking,
        "CDLKICKINGBYLENGTH" => FuncId::Cdlkickingbylength,
        "CDLLADDERBOTTOM" => FuncId::Cdlladderbottom,
        "CDLLONGLEGGEDDOJI" => FuncId::Cdllongleggeddoji,
        "CDLLONGLINE" => FuncId::Cdllongline,
        "CDLMARUBOZU" => FuncId::Cdlmarubozu,
        "CDLMATCHINGLOW" => FuncId::Cdlmatchinglow,
        "CDLMATHOLD" => FuncId::Cdlmathold,
        "CDLMORNINGDOJISTAR" => FuncId::Cdlmorningdojistar,
        "CDLMORNINGSTAR" => FuncId::Cdlmorningstar,
        "CDLONNECK" => FuncId::Cdlonneck,
        "CDLPIERCING" => FuncId::Cdlpiercing,
        "CDLRICKSHAWMAN" => FuncId::Cdlrickshawman,
        "CDLRISEFALL3METHODS" => FuncId::Cdlrisefall3methods,
        "CDLSEPARATINGLINES" => FuncId::Cdlseparatinglines,
        "CDLSHOOTINGSTAR" => FuncId::Cdlshootingstar,
        "CDLSHORTLINE" => FuncId::Cdlshortline,
        "CDLSPINNINGTOP" => FuncId::Cdlspinningtop,
        "CDLSTALLEDPATTERN" => FuncId::Cdlstalledpattern,
        "CDLSTICKSANDWICH" => FuncId::Cdlsticksandwich,
        "CDLTAKURI" => FuncId::Cdltakuri,
        "CDLTASUKIGAP" => FuncId::Cdltasukigap,
        "CDLTHRUSTING" => FuncId::Cdlthrusting,
        "CDLTRISTAR" => FuncId::Cdltristar,
        "CDLUNIQUE3RIVER" => FuncId::Cdlunique3river,
        "CDLUPSIDEGAP2CROWS" => FuncId::Cdlupsidegap2crows,
        "CDLXSIDEGAP3METHODS" => FuncId::Cdlxsidegap3methods,
        "CEIL" => FuncId::Ceil,
        "CMO" => FuncId::Cmo,
        "CORREL" => FuncId::Correl,
        "COS" => FuncId::Cos,
        "COSH" => FuncId::Cosh,
        "DEMA" => FuncId::Dema,
        "DIV" => FuncId::Div,
        "DX" => FuncId::Dx,
        "EMA" => FuncId::Ema,
        "EXP" => FuncId::Exp,
        "FLOOR" => FuncId::Floor,
        "HT_DCPERIOD" => FuncId::HtDcperiod,
        "HT_DCPHASE" => FuncId::HtDcphase,
        "HT_PHASOR" => FuncId::HtPhasor,
        "HT_SINE" => FuncId::HtSine,
        "HT_TRENDLINE" => FuncId::HtTrendline,
        "HT_TRENDMODE" => FuncId::HtTrendmode,
        "IMI" => FuncId::Imi,
        "KAMA" => FuncId::Kama,
        "LINEARREG" => FuncId::Linearreg,
        "LINEARREG_ANGLE" => FuncId::LinearregAngle,
        "LINEARREG_INTERCEPT" => FuncId::LinearregIntercept,
        "LINEARREG_SLOPE" => FuncId::LinearregSlope,
        "LN" => FuncId::Ln,
        "LOG10" => FuncId::Log10,
        "MA" => FuncId::Ma,
        "MACD" => FuncId::Macd,
        "MACDEXT" => FuncId::Macdext,
        "MACDFIX" => FuncId::Macdfix,
        "MAMA" => FuncId::Mama,
        "MAVP" => FuncId::Mavp,
        "MAX" => FuncId::Max,
        "MAXINDEX" => FuncId::Maxindex,
        "MEDPRICE" => FuncId::Medprice,
        "MFI" => FuncId::Mfi,
        "MIDPOINT" => FuncId::Midpoint,
        "MIDPRICE" => FuncId::Midprice,
        "MIN" => FuncId::Min,
        "MININDEX" => FuncId::Minindex,
        "MINMAX" => FuncId::Minmax,
        "MINMAXINDEX" => FuncId::Minmaxindex,
        "MINUS_DI" => FuncId::MinusDi,
        "MINUS_DM" => FuncId::MinusDm,
        "MOM" => FuncId::Mom,
        "MULT" => FuncId::Mult,
        "NATR" => FuncId::Natr,
        "OBV" => FuncId::Obv,
        "PLUS_DI" => FuncId::PlusDi,
        "PLUS_DM" => FuncId::PlusDm,
        "PPO" => FuncId::Ppo,
        "ROC" => FuncId::Roc,
        "ROCP" => FuncId::Rocp,
        "ROCR" => FuncId::Rocr,
        "ROCR100" => FuncId::Rocr100,
        "RSI" => FuncId::Rsi,
        "SAR" => FuncId::Sar,
        "SAREXT" => FuncId::Sarext,
        "SIN" => FuncId::Sin,
        "SINH" => FuncId::Sinh,
        "SMA" => FuncId::Sma,
        "SQRT" => FuncId::Sqrt,
        "STDDEV" => FuncId::Stddev,
        "STOCH" => FuncId::Stoch,
        "STOCHF" => FuncId::Stochf,
        "STOCHRSI" => FuncId::Stochrsi,
        "SUB" => FuncId::Sub,
        "SUM" => FuncId::Sum,
        "T3" => FuncId::T3,
        "TAN" => FuncId::Tan,
        "TANH" => FuncId::Tanh,
        "TEMA" => FuncId::Tema,
        "TRANGE" => FuncId::Trange,
        "TRIMA" => FuncId::Trima,
        "TRIX" => FuncId::Trix,
        "TSF" => FuncId::Tsf,
        "TYPPRICE" => FuncId::Typprice,
        "ULTOSC" => FuncId::Ultosc,
        "VAR" => FuncId::Var,
        "WCLPRICE" => FuncId::Wclprice,
        "WILLR" => FuncId::Willr,
        "WMA" => FuncId::Wma,
        _ => return None,
    })
}

/// C-style variant returning the familiar `RetCode` error channel.
pub fn get_func_handle_rc(name: &str) -> Result<FuncId, crate::RetCode> {
    get_func_handle(name).ok_or(crate::RetCode::BadParam)
}

/// Function metadata for a handle (infallible — `FuncId` cannot be invalid).
#[inline] pub fn get_func_info(handle: FuncId) -> &'static FuncInfo { handle.info() }
/// Required-input metadata by index (`None` if out of range).
#[inline] pub fn get_input_parameter_info(handle: FuncId, index: usize) -> Option<&'static InputInfo> { handle.info().inputs.get(index) }
/// Optional-input metadata by index (`None` if out of range).
#[inline] pub fn get_opt_input_parameter_info(handle: FuncId, index: usize) -> Option<&'static OptInputInfo> { handle.info().opt_inputs.get(index) }
/// Output metadata by index (`None` if out of range).
#[inline] pub fn get_output_parameter_info(handle: FuncId, index: usize) -> Option<&'static OutputInfo> { handle.info().outputs.get(index) }

/// Iterate metadata for every function (idiomatic replacement for C's `TA_ForEachFunc`).
#[inline] pub fn funcs() -> impl Iterator<Item = &'static FuncInfo> + Clone { FUNCS.iter() }
/// Iterate functions in a given group.
#[inline] pub fn funcs_in_group(group: Group) -> impl Iterator<Item = &'static FuncInfo> + Clone { FUNCS.iter().filter(move |f| f.group == group) }
/// C-style enumeration wrapper, for porters who prefer the callback shape.
pub fn for_each_func<F: FnMut(&'static FuncInfo)>(mut f: F) { for fi in FUNCS.iter() { f(fi); } }

/// All function groups (no allocation, unlike C's `TA_GroupTableAlloc`).
#[inline] pub fn groups() -> &'static [Group] { Group::ALL }

/// Rust analog of C's `TA_FunctionDescriptionXML()` — the full machine-readable XML
/// description of every function. Byte-identical to the generated `ta_func_api.xml`
/// (embedded via `include_str!`), which C's `TA_FunctionDescriptionXML` also bakes.
pub fn function_description_xml() -> &'static str {
    include_str!("ta_func_api.xml")
}

#[cfg(test)]
mod registry_tests {
    use super::*;

    #[test]
    fn count_matches_table_and_indices_align() {
        assert_eq!(FuncId::COUNT, FUNCS.len());
        for (i, f) in FUNCS.iter().enumerate() {
            assert_eq!(f.id as usize, i, "FuncId discriminant must equal its FUNCS index");
        }
    }

    #[test]
    fn name_handle_roundtrip() {
        for f in FUNCS.iter() {
            assert_eq!(get_func_handle(f.name), Some(f.id), "handle lookup for {}", f.name);
            assert_eq!(f.id.name(), f.name);
            assert_eq!(get_func_info(f.id).name, f.name);
        }
    }

    #[test]
    fn unknown_name_is_none() {
        assert_eq!(get_func_handle("definitely_not_a_ta_func"), None);
        assert!(get_func_handle_rc("definitely_not_a_ta_func").is_err());
    }

    #[test]
    fn groups_cover_every_func() {
        assert_eq!(groups(), Group::ALL);
        for f in FUNCS.iter() {
            assert!(Group::ALL.contains(&f.group), "{} group not in Group::ALL", f.name);
            assert!(!f.group.as_str().is_empty());
        }
    }

    #[test]
    fn funcs_in_group_partitions_all() {
        let total: usize = Group::ALL.iter().map(|g| funcs_in_group(*g).count()).sum();
        assert_eq!(total, FuncId::COUNT);
        assert_eq!(funcs().count(), FuncId::COUNT);
    }

    #[test]
    fn param_index_bounds() {
        for f in FUNCS.iter() {
            assert!(get_input_parameter_info(f.id, f.nb_input()).is_none());
            assert!(get_opt_input_parameter_info(f.id, f.nb_opt_input()).is_none());
            assert!(get_output_parameter_info(f.id, f.nb_output()).is_none());
            if f.nb_input() > 0 { assert!(get_input_parameter_info(f.id, 0).is_some()); }
            if f.nb_output() > 0 { assert!(get_output_parameter_info(f.id, 0).is_some()); }
        }
    }

    #[test]
    fn for_each_func_visits_all() {
        let mut n = 0;
        for_each_func(|_| n += 1);
        assert_eq!(n, FuncId::COUNT);
    }

    #[test]
    fn function_description_xml_is_sane() {
        let xml = function_description_xml();
        assert!(xml.starts_with("<?xml"));
        assert!(xml.contains("<FinancialFunctions>"));
        assert!(xml.len() > 500);
    }
}
