{
  "indicators": [
    {
      "type": "ChandelierExit",
      "class_name": "ChandelierExit",
      "name": "Chandelier Exit indicator primitive.",
      "description": "Calculates the Chandelier Exit technical indicator which combines the highest price over a period with ATR to identify potential stop levels.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for ChandelierExit indicator.",
        "properties": {
          "period": {
            "default": 60,
            "description": "The lookback period for highest high and ATR",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "multiplier": {
            "default": 4.0,
            "description": "The ATR multiplier",
            "exclusiveMinimum": 0,
            "title": "Multiplier",
            "type": "number"
          },
          "add_ma": {
            "default": false,
            "description": "Whether to also calculate MA",
            "title": "Add Ma",
            "type": "boolean"
          },
          "ma_period": {
            "default": 250,
            "description": "The period for MA calculation if add_ma=True",
            "exclusiveMinimum": 0,
            "title": "Ma Period",
            "type": "integer"
          }
        },
        "title": "ChandelierExitParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "Constant",
      "class_name": "Constant",
      "name": "Constant indicator primitive.",
      "description": "Generates a time series with a fixed value, with the same length as the input data.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Constant indicator.",
        "properties": {
          "value": {
            "default": 1.0,
            "description": "The constant value to generate",
            "title": "Value",
            "type": "number"
          }
        },
        "title": "ConstantParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": "variable",
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          },
          {
            "name": "kwargs",
            "type": "_empty"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "DonchianChannel",
      "class_name": "DonchianChannel",
      "name": "Donchian Channel multi-output indicator.",
      "description": "Calculates the rolling High/Low range over a lookback period with audited prior-completed-bar semantics, plus the derived midpoint and width of the channel. Outputs (all sharing the same index and NaN validity mask): * ``upper``  -- rolling maximum of ``upper_column`` * ``lower``  -- rolling minimum of ``lower_column`` * ``middle`` -- ``(upper + lower) / 2`` * ``width``  -- ``upper - lower`` Example (20-day upper breakout / 10-day lower exit, both excluding the current bar):: {\"id\": \"entry_channel\", \"type\": \"DonchianChannel\", \"params\": {\"period\": 20, \"upper_column\": \"High\", \"lower_column\": \"Low\", \"exclude_current\": true}} {\"id\": \"exit_channel\", \"type\": \"DonchianChannel\", \"params\": {\"period\": 10, \"upper_column\": \"High\", \"lower_column\": \"Low\", \"exclude_current\": true}} Entry compares ``Close`` against ``entry_channel.upper``, exit compares ``Close`` against ``exit_channel.lower``. The existing signal state machine remains the authority for BUY/HOLD/SELL/EMPTY transitions.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for DonchianChannel indicator.",
        "properties": {
          "period": {
            "default": 20,
            "description": "Number of bars in the channel window. Must be >= 1.",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "upper_column": {
            "default": "High",
            "description": "Column used to build the upper channel (rolling maximum).",
            "title": "Upper Column",
            "type": "string"
          },
          "lower_column": {
            "default": "Low",
            "description": "Column used to build the lower channel (rolling minimum).",
            "title": "Lower Column",
            "type": "string"
          },
          "exclude_current": {
            "default": true,
            "description": "If True, the channel value at bar t uses only completed bars ending at t-1 (upper[t]=max(column[t-period .. t-1])). This is the breakout-safe default. If False, the channel is an ordinary rolling range that includes bar t.",
            "title": "Exclude Current",
            "type": "boolean"
          }
        },
        "title": "DonchianChannelParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Dict",
        "names": [
          "upper",
          "lower",
          "middle",
          "width"
        ]
      },
      "output_names": [
        "upper",
        "lower",
        "middle",
        "width"
      ]
    },
    {
      "type": "HighestValue",
      "class_name": "HighestValue",
      "name": "Indicator that calculates the highest value over a lookback period.",
      "description": "This indicator finds the highest value of a specified column (e.g., High, Close) over a given lookback period. This can be used for identifying potential resistance levels, calculating Donchian channels, or as components in other technical indicators.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for extreme value indicators.",
        "properties": {
          "column": {
            "default": "Close",
            "description": "Column name to use from the input DataFrame",
            "title": "Column",
            "type": "string"
          },
          "period": {
            "default": 14,
            "description": "Lookback period for finding extreme values",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "output_format": {
            "default": "series",
            "description": "Output format",
            "enum": [
              "series",
              "dataframe"
            ],
            "title": "Output Format",
            "type": "string"
          }
        },
        "title": "ExtremeIndicatorParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "LowestValue",
      "class_name": "LowestValue",
      "name": "Indicator that calculates the lowest value over a lookback period.",
      "description": "This indicator finds the lowest value of a specified column (e.g., Low, Close) over a given lookback period. This can be used for identifying potential support levels, calculating Donchian channels, or as components in other technical indicators.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for extreme value indicators.",
        "properties": {
          "column": {
            "default": "Close",
            "description": "Column name to use from the input DataFrame",
            "title": "Column",
            "type": "string"
          },
          "period": {
            "default": 14,
            "description": "Lookback period for finding extreme values",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "output_format": {
            "default": "series",
            "description": "Output format",
            "enum": [
              "series",
              "dataframe"
            ],
            "title": "Output Format",
            "type": "string"
          }
        },
        "title": "ExtremeIndicatorParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "PercentFromHighest",
      "class_name": "PercentFromHighest",
      "name": "Indicator that calculates the percent distance from the highest value.",
      "description": "This indicator computes how far the current price is from the highest value over a given lookback period, expressed as a percentage. This can be useful for identifying potential entry or exit points based on price pullbacks.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for extreme value indicators.",
        "properties": {
          "column": {
            "default": "Close",
            "description": "Column name to use from the input DataFrame",
            "title": "Column",
            "type": "string"
          },
          "period": {
            "default": 14,
            "description": "Lookback period for finding extreme values",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "output_format": {
            "default": "series",
            "description": "Output format",
            "enum": [
              "series",
              "dataframe"
            ],
            "title": "Output Format",
            "type": "string"
          }
        },
        "title": "ExtremeIndicatorParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "PercentFromLowest",
      "class_name": "PercentFromLowest",
      "name": "Indicator that calculates the percent distance from the lowest value.",
      "description": "This indicator computes how far the current price is from the lowest value over a given lookback period, expressed as a percentage. This can be useful for identifying potential entry or exit points based on price rebounds.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for extreme value indicators.",
        "properties": {
          "column": {
            "default": "Close",
            "description": "Column name to use from the input DataFrame",
            "title": "Column",
            "type": "string"
          },
          "period": {
            "default": 14,
            "description": "Lookback period for finding extreme values",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "output_format": {
            "default": "series",
            "description": "Output format",
            "enum": [
              "series",
              "dataframe"
            ],
            "title": "Output Format",
            "type": "string"
          }
        },
        "title": "ExtremeIndicatorParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "DebtRatio",
      "class_name": "DebtRatio",
      "name": "Debt ratio fundamental indicator primitive.",
      "description": "Reads the debt ratio series from the configured column.",
      "params": {
        "additionalProperties": false,
        "properties": {
          "column": {
            "default": "debt_ratio",
            "description": "Debt ratio column",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "DebtRatioParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "OperatingCashflow",
      "class_name": "OperatingCashflow",
      "name": "Operating cash flow fundamental indicator primitive.",
      "description": "Reads the operating cash flow series from the configured column.",
      "params": {
        "additionalProperties": false,
        "properties": {
          "column": {
            "default": "operating_cashflow",
            "description": "Operating cash flow column",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "OperatingCashflowParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "PE_TTM",
      "class_name": "PETTM",
      "name": "PE TTM fundamental indicator primitive.",
      "description": "Reads the trailing-twelve-month PE series from the configured column.",
      "params": {
        "additionalProperties": false,
        "properties": {
          "column": {
            "default": "pe_ttm",
            "description": "PE TTM column",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "PETTMParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "ROE",
      "class_name": "ROE",
      "name": "Return on equity fundamental indicator primitive.",
      "description": "Reads the ROE series from the configured column as a numeric time series.",
      "params": {
        "additionalProperties": false,
        "properties": {
          "column": {
            "default": "roe",
            "description": "Return on Equity column",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "ROEParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "RevenueYoY",
      "class_name": "RevenueYoY",
      "name": "Revenue YoY fundamental indicator primitive.",
      "description": "Reads the year-over-year revenue growth series from the configured column.",
      "params": {
        "additionalProperties": false,
        "properties": {
          "column": {
            "default": "revenue_yoy",
            "description": "Revenue YoY column",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "RevenueYoYParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "MACD",
      "class_name": "MACD",
      "name": "Moving Average Convergence Divergence indicator primitive.",
      "description": "Calculates the MACD technical indicator which shows the relationship between two moving averages of a security's price. This is a multi-output indicator that produces three separate values: 1. MACD Line: The difference between fast and slow EMAs 2. Signal Line: An EMA of the MACD Line 3. Histogram: The difference between MACD Line and Signal Line",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for MACD indicator.",
        "properties": {
          "fast_period": {
            "default": 12,
            "description": "The period for the fast EMA",
            "exclusiveMinimum": 0,
            "title": "Fast Period",
            "type": "integer"
          },
          "slow_period": {
            "default": 26,
            "description": "The period for the slow EMA",
            "exclusiveMinimum": 0,
            "title": "Slow Period",
            "type": "integer"
          },
          "signal_period": {
            "default": 9,
            "description": "The period for the signal EMA",
            "exclusiveMinimum": 0,
            "title": "Signal Period",
            "type": "integer"
          },
          "column": {
            "default": "Close",
            "description": "The column to calculate MACD on",
            "title": "Column",
            "type": "string"
          },
          "output_format": {
            "default": "dict",
            "description": "Output format, either 'dict' or 'dataframe'",
            "enum": [
              "dict",
              "dataframe"
            ],
            "title": "Output Format",
            "type": "string"
          }
        },
        "title": "MACDParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Dict",
        "names": [
          "macd",
          "signal",
          "histogram"
        ]
      },
      "output_names": [
        "macd",
        "signal",
        "histogram"
      ]
    },
    {
      "type": "RSI",
      "class_name": "RSI",
      "name": "Relative Strength Index indicator primitive.",
      "description": "Calculates the RSI technical indicator which measures the magnitude of recent price changes to evaluate overbought or oversold conditions.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for RSI indicator.",
        "properties": {
          "period": {
            "default": 14,
            "description": "The lookback period for the RSI calculation",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "column": {
            "default": "Close",
            "description": "The column to calculate RSI on",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "RSIParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "RateOfChange",
      "class_name": "RateOfChange",
      "name": "Numeric decimal return over a fixed number of prior observations.",
      "description": "",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for the numeric rate-of-change feature.",
        "properties": {
          "periods": {
            "default": 1,
            "description": "Positive lookback in trading observations",
            "exclusiveMinimum": 0,
            "title": "Periods",
            "type": "integer"
          },
          "column": {
            "default": "Close",
            "description": "Input data column used to calculate decimal returns",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "RateOfChangeParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "EMA",
      "class_name": "EMA",
      "name": "Exponential Moving Average indicator primitive.",
      "description": "Uses pandas' exponential weighted moving average (ewm) for EMA calculation. EMA gives more weight to recent prices compared to SMA.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Exponential Moving Average indicator.",
        "properties": {
          "period": {
            "default": 20,
            "description": "The lookback period for the moving average",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "column": {
            "default": "Close",
            "description": "The column to calculate EMA on",
            "title": "Column",
            "type": "string"
          },
          "adjust": {
            "default": false,
            "description": "Specify if the weights should be normalized",
            "title": "Adjust",
            "type": "boolean"
          }
        },
        "title": "EMAParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "SMA",
      "class_name": "SMA",
      "name": "Simple Moving Average indicator primitive.",
      "description": "Uses pandas' rolling window calculation for Simple Moving Average computation.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Simple Moving Average indicator.",
        "properties": {
          "period": {
            "default": 20,
            "description": "The lookback period for the moving average",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "column": {
            "default": "Close",
            "description": "The column to calculate SMA on",
            "title": "Column",
            "type": "string"
          }
        },
        "title": "SMAParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "Stochastic",
      "class_name": "Stochastic",
      "name": "Stochastic Oscillator indicator primitive.",
      "description": "Calculates the Stochastic Oscillator which compares a security's closing price to its price range over a given time period. The indicator consists of two lines: %K (the main line) and %D (the signal line).",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Stochastic Oscillator.",
        "properties": {
          "k_period": {
            "default": 14,
            "description": "The lookback period for %K calculation",
            "exclusiveMinimum": 0,
            "title": "K Period",
            "type": "integer"
          },
          "d_period": {
            "default": 3,
            "description": "The period for the %D moving average",
            "exclusiveMinimum": 0,
            "title": "D Period",
            "type": "integer"
          },
          "d_method": {
            "default": "simple",
            "description": "The method for calculating %D",
            "enum": [
              "simple",
              "exponential"
            ],
            "title": "D Method",
            "type": "string"
          },
          "output_format": {
            "default": "dict",
            "description": "Output format",
            "enum": [
              "dict",
              "dataframe"
            ],
            "title": "Output Format",
            "type": "string"
          }
        },
        "title": "StochasticParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Union",
        "names": [
          "k",
          "d"
        ]
      },
      "output_names": [
        "k",
        "d"
      ]
    },
    {
      "type": "ATR",
      "class_name": "ATR",
      "name": "Average True Range indicator primitive.",
      "description": "Calculates the ATR technical indicator which measures market volatility by decomposing the entire range of an asset price for a specified period.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for ATR indicator.",
        "properties": {
          "period": {
            "default": 14,
            "description": "The lookback period for calculating ATR",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "method": {
            "default": "sma",
            "description": "The calculation method",
            "enum": [
              "sma",
              "ema"
            ],
            "title": "Method",
            "type": "string"
          }
        },
        "title": "ATRParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "BollingerBands",
      "class_name": "BollingerBands",
      "name": "Bollinger Bands indicator primitive.",
      "description": "Calculates Bollinger Bands, which consist of: - Middle band: SMA/EMA of the price - Upper band: Middle band + (standard deviation * multiplier) - Lower band: Middle band - (standard deviation * multiplier) This is a multi-output indicator returning a dictionary of Series.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Bollinger Bands indicator.",
        "properties": {
          "period": {
            "default": 20,
            "description": "The lookback period for the moving average",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "std_dev": {
            "default": 2.0,
            "description": "Standard deviation multiplier",
            "exclusiveMinimum": 0,
            "title": "Std Dev",
            "type": "number"
          },
          "column": {
            "default": "Close",
            "description": "The column to calculate bands on",
            "title": "Column",
            "type": "string"
          },
          "method": {
            "default": "sma",
            "description": "MA calculation method",
            "enum": [
              "sma",
              "ema"
            ],
            "title": "Method",
            "type": "string"
          }
        },
        "title": "BollingerBandsParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "numeric",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Dict",
        "names": [
          "middle",
          "upper",
          "lower"
        ]
      },
      "output_names": [
        "middle",
        "upper",
        "lower"
      ]
    }
  ],
  "signals": [
    {
      "type": "Comparison",
      "class_name": "Comparison",
      "name": "General comparison signal primitive.",
      "description": "Compares values using a specified comparison operator. Supports different comparison types and an optional threshold value.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Comparison signal.",
        "properties": {
          "comparison": {
            "default": "greater",
            "description": "Type of comparison to perform",
            "enum": [
              "greater",
              "less",
              "equal",
              "greater_equal",
              "less_equal",
              "not_equal"
            ],
            "title": "Comparison",
            "type": "string"
          },
          "threshold": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Threshold value for comparison when only one input is provided",
            "title": "Threshold"
          },
          "epsilon": {
            "default": 1e-10,
            "description": "Small value to avoid floating point precision issues",
            "minimum": 0.0,
            "title": "Epsilon",
            "type": "number"
          }
        },
        "title": "ComparisonParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Crossover",
      "class_name": "Crossover",
      "name": "Detects when one series crosses above another.",
      "description": "Signal is True when series_a crosses above series_b. Supports two modes: - 'cross': Requires actual crossing (previous <= and current >) - 'simple': Simple comparison (current >), used to replicate DualMovingAverageStrategy",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Crossover signal.",
        "properties": {
          "mode": {
            "default": "cross",
            "description": "Comparison mode: 'cross' for actual crossing, 'simple' for basic comparison",
            "enum": [
              "cross",
              "simple"
            ],
            "title": "Mode",
            "type": "string"
          }
        },
        "title": "CrossoverParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Crossunder",
      "class_name": "Crossunder",
      "name": "Detects when one series crosses below another.",
      "description": "Signal is True when series_a crosses below series_b. Supports two modes: - 'cross': Requires actual crossing (previous >= and current <) - 'simple': Simple comparison (current <), used to replicate DualMovingAverageStrategy",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Crossunder signal.",
        "properties": {
          "mode": {
            "default": "cross",
            "description": "Comparison mode: 'cross' for actual crossing, 'simple' for basic comparison",
            "enum": [
              "cross",
              "simple"
            ],
            "title": "Mode",
            "type": "string"
          }
        },
        "title": "CrossunderParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "GreaterThan",
      "class_name": "GreaterThan",
      "name": "Compares if one series is greater than another.",
      "description": "Signal is True when series_a is greater than series_b.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for GreaterThan signal.",
        "properties": {
          "epsilon": {
            "default": 0.0,
            "description": "Small value for floating point comparison tolerance",
            "minimum": 0.0,
            "title": "Epsilon",
            "type": "number"
          }
        },
        "title": "GreaterThanParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "InRange",
      "class_name": "InRange",
      "name": "Check if a series is within a specified range.",
      "description": "Signal is True when the value is between lower and upper bounds. Supports inclusive and exclusive range boundaries.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for InRange signal.",
        "properties": {
          "include_lower": {
            "default": true,
            "description": "Whether to include the lower bound",
            "title": "Include Lower",
            "type": "boolean"
          },
          "include_upper": {
            "default": true,
            "description": "Whether to include the upper bound",
            "title": "Include Upper",
            "type": "boolean"
          }
        },
        "title": "InRangeParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "LessThan",
      "class_name": "LessThan",
      "name": "Compares if one series is less than another.",
      "description": "Signal is True when series_a is less than series_b.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for LessThan signal.",
        "properties": {
          "epsilon": {
            "default": 0.0,
            "description": "Small value for floating point comparison tolerance",
            "minimum": 0.0,
            "title": "Epsilon",
            "type": "number"
          }
        },
        "title": "LessThanParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "CrossAbove",
      "class_name": "CrossAbove",
      "name": "CrossAbove signal primitive.",
      "description": "Detects when one signal crosses above another signal. True when signal_a was below signal_b in previous period and is now above signal_b.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for CrossAbove and CrossBelow signals.",
        "properties": {
          "threshold": {
            "default": 0.0,
            "description": "Additional threshold to require for crossing",
            "title": "Threshold",
            "type": "number"
          },
          "strict": {
            "default": false,
            "description": "If True, requires strict comparison for prior period",
            "title": "Strict",
            "type": "boolean"
          }
        },
        "title": "CrossCompositeParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "CrossBelow",
      "class_name": "CrossBelow",
      "name": "CrossBelow signal primitive.",
      "description": "Detects when one signal crosses below another signal. True when signal_a was above signal_b in previous period and is now below signal_b.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for CrossAbove and CrossBelow signals.",
        "properties": {
          "threshold": {
            "default": 0.0,
            "description": "Additional threshold to require for crossing",
            "title": "Threshold",
            "type": "number"
          },
          "strict": {
            "default": false,
            "description": "If True, requires strict comparison for prior period",
            "title": "Strict",
            "type": "boolean"
          }
        },
        "title": "CrossCompositeParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "CrossSectionalRank",
      "class_name": "CrossSectionalRank",
      "name": "Deterministic ordinal rank across eligible symbols on a decision session.",
      "description": "",
      "params": {
        "additionalProperties": false,
        "properties": {
          "direction": {
            "default": "descending",
            "description": "Feature ordering direction",
            "pattern": "^(ascending|descending)$",
            "title": "Direction",
            "type": "string"
          }
        },
        "title": "CrossSectionalRankParams",
        "type": "object"
      },
      "evaluation_domain": "cross_sectional",
      "output_type": "rank",
      "inputs": {
        "count": 3,
        "types": [
          "numeric",
          "boolean",
          "cadence"
        ]
      },
      "outputs": {
        "type": "rank"
      }
    },
    {
      "type": "EqualWeight",
      "class_name": "EqualWeight",
      "name": "Complete equal-weight vector on rebalance dates and NaN between them.",
      "description": "",
      "params": {
        "additionalProperties": false,
        "properties": {
          "rebalance_policy": {
            "default": "scheduled",
            "description": "Emit on every scheduled decision or only when selected membership changes",
            "enum": [
              "scheduled",
              "membership_change"
            ],
            "title": "Rebalance Policy",
            "type": "string"
          }
        },
        "title": "EqualWeightParams",
        "type": "object"
      },
      "evaluation_domain": "cross_sectional",
      "output_type": "weight",
      "inputs": {
        "count": 2,
        "types": [
          "selection",
          "cadence"
        ]
      },
      "outputs": {
        "type": "weight"
      }
    },
    {
      "type": "RebalanceCadence",
      "class_name": "RebalanceCadence",
      "name": "Portfolio-calendar cadence with first-observed-period bootstrap control.",
      "description": "",
      "params": {
        "additionalProperties": false,
        "properties": {
          "frequency": {
            "default": "monthly_first_session",
            "description": "Portfolio decision-session cadence",
            "enum": [
              "daily",
              "weekly_first_session",
              "monthly_first_session"
            ],
            "title": "Frequency",
            "type": "string"
          },
          "bootstrap_on_first_session": {
            "default": true,
            "description": "For weekly/monthly cadence, act on the first observed Portfolio session when true; when false, wait for the next calendar period. Daily cadence is unaffected.",
            "title": "Bootstrap On First Session",
            "type": "boolean"
          }
        },
        "title": "RebalanceCadenceParams",
        "type": "object"
      },
      "evaluation_domain": "cross_sectional",
      "output_type": "cadence",
      "inputs": {
        "count": 0,
        "types": []
      },
      "outputs": {
        "type": "cadence"
      }
    },
    {
      "type": "TopN",
      "class_name": "TopN",
      "name": "Select the lowest N finite ordinal ranks and carry membership between decisions.",
      "description": "",
      "params": {
        "additionalProperties": false,
        "properties": {
          "n": {
            "default": 1,
            "description": "Maximum selected symbol count",
            "exclusiveMinimum": 0,
            "title": "N",
            "type": "integer"
          }
        },
        "title": "TopNParams",
        "type": "object"
      },
      "evaluation_domain": "cross_sectional",
      "output_type": "selection",
      "inputs": {
        "count": 2,
        "types": [
          "rank",
          "cadence"
        ]
      },
      "outputs": {
        "type": "selection"
      }
    },
    {
      "type": "And",
      "class_name": "And",
      "name": "Logical AND operator for signal primitives.",
      "description": "Signal is True when both input signals are True.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for logical signal primitives.",
        "properties": {
          "fill_method": {
            "anyOf": [
              {
                "enum": [
                  "ffill",
                  "bfill"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Method to handle NaN values",
            "title": "Fill Method"
          }
        },
        "title": "LogicalParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Not",
      "class_name": "Not",
      "name": "Logical NOT operator for signal primitives.",
      "description": "Signal is True when the input signal is False, and vice versa.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Not signal primitive.",
        "properties": {
          "fill_method": {
            "anyOf": [
              {
                "enum": [
                  "ffill",
                  "bfill"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Method to handle NaN values",
            "title": "Fill Method"
          },
          "preserve_na": {
            "default": false,
            "description": "If True, NaN values remain NaN in the output",
            "title": "Preserve Na",
            "type": "boolean"
          }
        },
        "title": "NotParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Or",
      "class_name": "Or",
      "name": "Logical OR operator for signal primitives.",
      "description": "Signal is True when either input signal is True.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for logical signal primitives.",
        "properties": {
          "fill_method": {
            "anyOf": [
              {
                "enum": [
                  "ffill",
                  "bfill"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Method to handle NaN values",
            "title": "Fill Method"
          }
        },
        "title": "LogicalParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Add",
      "class_name": "Add",
      "name": "Signal that adds two time series and compares the result.",
      "description": "This signal adds two input series and compares the result against either a threshold value or a third input series.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for mathematical operation signals.",
        "properties": {
          "operation": {
            "default": "add",
            "description": "Type of operation to perform",
            "enum": [
              "add",
              "subtract",
              "multiply",
              "divide"
            ],
            "title": "Operation",
            "type": "string"
          },
          "comparison": {
            "default": "greater",
            "description": "Type of comparison",
            "enum": [
              "greater",
              "less",
              "equal",
              "greater_equal",
              "less_equal"
            ],
            "title": "Comparison",
            "type": "string"
          },
          "threshold": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Value to compare result against (if not comparing against another series)",
            "title": "Threshold"
          },
          "absolute": {
            "default": false,
            "description": "Whether to take the absolute value of the result before comparison",
            "title": "Absolute",
            "type": "boolean"
          },
          "return_calculation": {
            "default": false,
            "description": "If True, return the numeric calculation result instead of boolean comparison result. Supports multiple operands.",
            "title": "Return Calculation",
            "type": "boolean"
          }
        },
        "title": "MathOperationParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "dynamic",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Divide",
      "class_name": "Divide",
      "name": "Signal that divides one time series by another and compares the result.",
      "description": "This signal divides the first input series by the second and compares the result against either a threshold value or a third input series. Special handling is included to safely handle division by zero.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for mathematical operation signals.",
        "properties": {
          "operation": {
            "default": "divide",
            "description": "Type of operation to perform",
            "enum": [
              "add",
              "subtract",
              "multiply",
              "divide"
            ],
            "title": "Operation",
            "type": "string"
          },
          "comparison": {
            "default": "greater",
            "description": "Type of comparison",
            "enum": [
              "greater",
              "less",
              "equal",
              "greater_equal",
              "less_equal"
            ],
            "title": "Comparison",
            "type": "string"
          },
          "threshold": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Value to compare result against (if not comparing against another series)",
            "title": "Threshold"
          },
          "absolute": {
            "default": false,
            "description": "Whether to take the absolute value of the result before comparison",
            "title": "Absolute",
            "type": "boolean"
          },
          "return_calculation": {
            "default": false,
            "description": "If True, return the numeric calculation result instead of boolean comparison result. Supports multiple operands.",
            "title": "Return Calculation",
            "type": "boolean"
          }
        },
        "title": "MathOperationParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "dynamic",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Multiply",
      "class_name": "Multiply",
      "name": "Signal that multiplies two time series and compares the result.",
      "description": "This signal multiplies two input series and compares the result against either a threshold value or a third input series.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for mathematical operation signals.",
        "properties": {
          "operation": {
            "default": "multiply",
            "description": "Type of operation to perform",
            "enum": [
              "add",
              "subtract",
              "multiply",
              "divide"
            ],
            "title": "Operation",
            "type": "string"
          },
          "comparison": {
            "default": "greater",
            "description": "Type of comparison",
            "enum": [
              "greater",
              "less",
              "equal",
              "greater_equal",
              "less_equal"
            ],
            "title": "Comparison",
            "type": "string"
          },
          "threshold": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Value to compare result against (if not comparing against another series)",
            "title": "Threshold"
          },
          "absolute": {
            "default": false,
            "description": "Whether to take the absolute value of the result before comparison",
            "title": "Absolute",
            "type": "boolean"
          },
          "return_calculation": {
            "default": false,
            "description": "If True, return the numeric calculation result instead of boolean comparison result. Supports multiple operands.",
            "title": "Return Calculation",
            "type": "boolean"
          }
        },
        "title": "MathOperationParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "dynamic",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Subtract",
      "class_name": "Subtract",
      "name": "Signal that subtracts one time series from another and compares the result.",
      "description": "This signal subtracts the second input series from the first and compares the result against either a threshold value or a third input series.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for mathematical operation signals.",
        "properties": {
          "operation": {
            "default": "subtract",
            "description": "Type of operation to perform",
            "enum": [
              "add",
              "subtract",
              "multiply",
              "divide"
            ],
            "title": "Operation",
            "type": "string"
          },
          "comparison": {
            "default": "greater",
            "description": "Type of comparison",
            "enum": [
              "greater",
              "less",
              "equal",
              "greater_equal",
              "less_equal"
            ],
            "title": "Comparison",
            "type": "string"
          },
          "threshold": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Value to compare result against (if not comparing against another series)",
            "title": "Threshold"
          },
          "absolute": {
            "default": false,
            "description": "Whether to take the absolute value of the result before comparison",
            "title": "Absolute",
            "type": "boolean"
          },
          "return_calculation": {
            "default": false,
            "description": "If True, return the numeric calculation result instead of boolean comparison result. Supports multiple operands.",
            "title": "Return Calculation",
            "type": "boolean"
          }
        },
        "title": "MathOperationParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "dynamic",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "PercentChange",
      "class_name": "PercentChange",
      "name": "Calculate percent change signal over specified period.",
      "description": "Signal is True when the percent change meets the threshold criteria.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for PercentChange signal.",
        "properties": {
          "periods": {
            "default": 1,
            "description": "Number of periods to calculate change over",
            "exclusiveMinimum": 0,
            "title": "Periods",
            "type": "integer"
          },
          "threshold": {
            "default": 0,
            "description": "Value to compare percent change against",
            "title": "Threshold",
            "type": "number"
          },
          "comparison": {
            "default": "greater",
            "description": "Comparison type",
            "enum": [
              "greater",
              "less",
              "equal"
            ],
            "title": "Comparison",
            "type": "string"
          },
          "is_absolute": {
            "default": false,
            "description": "Whether to use absolute value of percent change",
            "title": "Is Absolute",
            "type": "boolean"
          }
        },
        "title": "PercentChangeParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "Streak",
      "class_name": "Streak",
      "name": "Streak pattern detection signal primitive.",
      "description": "Detects when a signal has occurred consecutively for a specified number of periods.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Streak pattern detection.",
        "properties": {
          "min_length": {
            "default": 2,
            "description": "Minimum number of consecutive occurrences required",
            "exclusiveMinimum": 0,
            "title": "Min Length",
            "type": "integer"
          },
          "max_length": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of consecutive occurrences to consider",
            "title": "Max Length"
          },
          "match_type": {
            "default": "true",
            "description": "Type of streak to detect",
            "enum": [
              "true",
              "false",
              "any"
            ],
            "title": "Match Type",
            "type": "string"
          }
        },
        "title": "StreakParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "StockBondSwitch",
      "class_name": "StockBondSwitch",
      "name": "Stock-Bond switching signal primitive.",
      "description": "This primitive implements a stock-bond switching strategy where: - When condition is True: hold stock ETF (symbols[0]) - When condition is False: hold bond ETF (symbols[1]) The primitive returns appropriate signals based on the current symbol being evaluated and the market condition. Convention: - symbols[0] should be the stock ETF - symbols[1] should be the bond ETF",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for StockBondSwitch signal.",
        "properties": {
          "default_to_stock": {
            "default": true,
            "description": "Whether to default to stock when condition is unavailable",
            "title": "Default To Stock",
            "type": "boolean"
          }
        },
        "title": "StockBondSwitchParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "boolean",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "condition_signal",
            "type": "Series"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "Lag",
      "class_name": "Lag",
      "name": "Lag (shift) a time series by a specified number of periods.",
      "description": "This primitive shifts data forward in time, meaning at any given date, you see the value from `periods` days ago. This is essential for: 1. Confirmation logic: Combine with And to require \"today AND yesterday\" 2. Avoiding look-ahead bias: Use previous day's values for signals 3. Implementing \"wait N days\" patterns Example usage for \"2 consecutive days below threshold\": ```json { \"id\": \"confirmed_sell\", \"type\": \"And\", \"inputs\": [ { \"ref\": \"below_threshold\" }, { \"type\": \"Lag\", \"params\": { \"periods\": 1 }, \"inputs\": [{ \"ref\": \"below_threshold\" }] } ] } ``` This evaluates: today_below AND yesterday_below → True only on day 2+",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for Lag signal primitive.",
        "properties": {
          "periods": {
            "default": 1,
            "description": "Number of periods to shift. Positive values shift forward (look back at past values).",
            "minimum": 0,
            "title": "Periods",
            "type": "integer"
          },
          "fill_value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Value to use for filling NaN positions created by the shift. For boolean series, use 0 (False) or 1 (True). None keeps NaN.",
            "title": "Fill Value"
          }
        },
        "title": "LagParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "dynamic",
      "inputs": {
        "count": "variable",
        "types": []
      },
      "outputs": {
        "type": "Union"
      }
    },
    {
      "type": "ConditionalWeight",
      "class_name": "ConditionalWeight",
      "name": "条件权重原语：根据布尔条件选择权重",
      "description": "用途： - PE>25时半仓，否则满仓 - RSI>70时减仓，否则正常仓位 - 任何基于条件的离散权重调整 输入：布尔条件序列 (pd.Series of bool) 输出：权重序列 (pd.Series of float, True→true_weight, False→false_weight) 示例配置： { \"id\": \"pe_weight\", \"type\": \"ConditionalWeight\", \"inputs\": [{\"ref\": \"pe_high\"}],  // pe_high是布尔条件 \"params\": { \"true_weight\": 0.5,   // PE高时 → 50%仓位 \"false_weight\": 1.0   // PE正常时 → 100%仓位 } }",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for ConditionalWeight primitive.",
        "properties": {
          "true_weight": {
            "description": "条件为True时的权重",
            "maximum": 1,
            "minimum": 0,
            "title": "True Weight",
            "type": "number"
          },
          "false_weight": {
            "description": "条件为False时的权重",
            "maximum": 1,
            "minimum": 0,
            "title": "False Weight",
            "type": "number"
          }
        },
        "required": [
          "true_weight",
          "false_weight"
        ],
        "title": "ConditionalWeightParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "weight",
      "inputs": {
        "count": "variable",
        "types": [
          {
            "name": "condition",
            "type": "_empty"
          }
        ]
      },
      "outputs": {
        "type": "_empty"
      }
    },
    {
      "type": "LinearScaleWeight",
      "class_name": "LinearScaleWeight",
      "name": "线性缩放权重原语：将指标值线性映射到权重范围",
      "description": "用途： - PE从15到30，仓位从100%到30%（平滑过渡） - RSI从30到70，仓位从30%到100% - 任何基于指标的连续权重调整 输入：数值指标序列 (pd.Series of float) 输出：线性映射的权重序列 (pd.Series of float) 映射公式： normalized = (indicator - min_indicator) / (max_indicator - min_indicator) weight = min_weight + normalized * (max_weight - min_weight) 示例配置： { \"id\": \"pe_smooth_weight\", \"type\": \"LinearScaleWeight\", \"inputs\": [{\"ref\": \"pe\"}],  // pe是数值指标 \"params\": { \"min_indicator\": 15,   // PE=15 \"max_indicator\": 30,   // PE=30 \"min_weight\": 1.0,     // → 100%仓位 \"max_weight\": 0.3,     // → 30%仓位 \"clip\": true           // 超出范围裁剪 } } 效果： PE值:     10   15   20   25   30   35 权重:    1.0  1.0  0.77 0.53 0.3  0.3  (clip=true)",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for LinearScaleWeight primitive.",
        "properties": {
          "min_indicator": {
            "description": "指标最小值",
            "title": "Min Indicator",
            "type": "number"
          },
          "max_indicator": {
            "description": "指标最大值",
            "title": "Max Indicator",
            "type": "number"
          },
          "min_weight": {
            "description": "映射到的最小权重",
            "maximum": 1,
            "minimum": 0,
            "title": "Min Weight",
            "type": "number"
          },
          "max_weight": {
            "description": "映射到的最大权重",
            "maximum": 1,
            "minimum": 0,
            "title": "Max Weight",
            "type": "number"
          },
          "clip": {
            "default": true,
            "description": "是否裁剪超出范围的值",
            "title": "Clip",
            "type": "boolean"
          }
        },
        "required": [
          "min_indicator",
          "max_indicator",
          "min_weight",
          "max_weight"
        ],
        "title": "LinearScaleWeightParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "weight",
      "inputs": {
        "count": "variable",
        "types": [
          {
            "name": "indicator",
            "type": "_empty"
          }
        ]
      },
      "outputs": {
        "type": "_empty"
      }
    }
  ],
  "market_transformers": [
    {
      "type": "ChandelierExitTransformer",
      "class_name": "ChandelierExitTransformer",
      "name": "Transformer that calculates Chandelier Exit stop level for market indicator data.",
      "description": "Chandelier Exit = Highest High(period) - ATR(period) * multiplier This is useful for trend-following strategies that use trailing stops.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for ChandelierExitTransformer.",
        "properties": {
          "indicator": {
            "description": "Market indicator code",
            "title": "Indicator",
            "type": "string"
          },
          "period": {
            "default": 30,
            "description": "Period for highest high and ATR calculation",
            "exclusiveMinimum": 0,
            "title": "Period",
            "type": "integer"
          },
          "multiplier": {
            "default": 2.0,
            "description": "ATR multiplier for stop calculation",
            "exclusiveMinimum": 0,
            "title": "Multiplier",
            "type": "number"
          }
        },
        "required": [
          "indicator"
        ],
        "title": "ChandelierExitTransformerParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "IdentityTransformer",
      "class_name": "IdentityTransformer",
      "name": "Identity transformer that returns original data without transformation.",
      "description": "This is useful when you need to reference raw market indicator values in signal calculations.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for IdentityTransformer.",
        "properties": {
          "indicator": {
            "description": "Market indicator code",
            "title": "Indicator",
            "type": "string"
          },
          "field": {
            "default": "Close",
            "description": "Field to use from the indicator data",
            "title": "Field",
            "type": "string"
          }
        },
        "required": [
          "indicator"
        ],
        "title": "IdentityTransformerParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "MovingAverageTransformer",
      "class_name": "MovingAverageTransformer",
      "name": "Transformer that calculates moving averages of market indicator data.",
      "description": "Supports simple, exponential, and weighted moving averages.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for MovingAverageTransformer.",
        "example": {
          "field": "Close",
          "indicator": "VIX",
          "method": "simple",
          "window": 20
        },
        "properties": {
          "indicator": {
            "description": "Market indicator code",
            "title": "Indicator",
            "type": "string"
          },
          "window": {
            "description": "Size of the moving average window",
            "exclusiveMinimum": 0,
            "title": "Window",
            "type": "integer"
          },
          "method": {
            "default": "simple",
            "description": "Type of moving average",
            "enum": [
              "simple",
              "exponential",
              "weighted"
            ],
            "title": "Method",
            "type": "string"
          },
          "field": {
            "default": "Close",
            "description": "Field to use from the indicator data",
            "title": "Field",
            "type": "string"
          }
        },
        "required": [
          "indicator",
          "window"
        ],
        "title": "MovingAverageTransformerParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "PercentileRankTransformer",
      "class_name": "PercentileRankTransformer",
      "name": "Transformer that calculates the percentile rank of market indicator values.",
      "description": "This is useful for normalizing indicators to a 0-100 scale based on historical distributions.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for PercentileRankTransformer.",
        "properties": {
          "indicator": {
            "description": "Market indicator code",
            "title": "Indicator",
            "type": "string"
          },
          "lookback": {
            "description": "Historical period for percentile calculation",
            "exclusiveMinimum": 0,
            "title": "Lookback",
            "type": "integer"
          },
          "field": {
            "default": "Close",
            "description": "Field to use from the indicator data",
            "title": "Field",
            "type": "string"
          }
        },
        "required": [
          "indicator",
          "lookback"
        ],
        "title": "PercentileRankTransformerParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "RSITransformer",
      "class_name": "RSITransformer",
      "name": "Transformer that calculates the Relative Strength Index (RSI) of market indicator values.",
      "description": "RSI is a momentum oscillator that measures the speed and magnitude of recent price changes to evaluate overbought or oversold conditions.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for RSITransformer.",
        "properties": {
          "indicator": {
            "description": "Market indicator code",
            "title": "Indicator",
            "type": "string"
          },
          "window": {
            "default": 14,
            "description": "Period for RSI calculation",
            "exclusiveMinimum": 0,
            "title": "Window",
            "type": "integer"
          },
          "field": {
            "default": "Close",
            "description": "Field to use from the indicator data",
            "title": "Field",
            "type": "string"
          }
        },
        "required": [
          "indicator"
        ],
        "title": "RSITransformerParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "RelativeStrengthTransformer",
      "class_name": "RelativeStrengthTransformer",
      "name": "Transformer that calculates the relative strength of a market indicator.",
      "description": "Relative strength is calculated as the ratio of current value to a reference value (typically a moving average or historical value).",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for RelativeStrengthTransformer.",
        "properties": {
          "indicator": {
            "description": "Market indicator code",
            "title": "Indicator",
            "type": "string"
          },
          "reference": {
            "description": "Reference method: 'ma', 'value', or 'lookback'",
            "title": "Reference",
            "type": "string"
          },
          "window": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Window size for 'ma' or 'lookback' reference",
            "title": "Window"
          },
          "value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Fixed value for 'value' reference",
            "title": "Value"
          },
          "field": {
            "default": "Close",
            "description": "Field to use from the indicator data",
            "title": "Field",
            "type": "string"
          }
        },
        "required": [
          "indicator",
          "reference"
        ],
        "title": "RelativeStrengthTransformerParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    },
    {
      "type": "ZScoreTransformer",
      "class_name": "ZScoreTransformer",
      "name": "Transformer that calculates Z-scores of market indicator values.",
      "description": "Z-score represents how many standard deviations a value is from the mean, useful for identifying extreme values.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for ZScoreTransformer.",
        "properties": {
          "indicator": {
            "description": "Market indicator code",
            "title": "Indicator",
            "type": "string"
          },
          "window": {
            "description": "Historical period for mean/std calculation",
            "exclusiveMinimum": 0,
            "title": "Window",
            "type": "integer"
          },
          "field": {
            "default": "Close",
            "description": "Field to use from the indicator data",
            "title": "Field",
            "type": "string"
          }
        },
        "required": [
          "indicator",
          "window"
        ],
        "title": "ZScoreTransformerParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 1,
        "types": [
          {
            "name": "data",
            "type": "DataFrame"
          }
        ]
      },
      "outputs": {
        "type": "Series"
      }
    }
  ],
  "capital_strategies": [
    {
      "type": "CashSweepPercentCapitalStrategy",
      "class_name": "CashSweepPercentCapitalStrategy",
      "name": "Percent-based capital strategy with optional cash sweep behavior.",
      "description": "- Main signal-driven positions use percent allocation semantics. - Optional sweep symbol is managed by capital hooks, not by trade signals.",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for CashSweepPercentCapitalStrategy.",
        "properties": {
          "initial_capital": {
            "default": 100000.0,
            "description": "Initial capital amount",
            "exclusiveMinimum": 0,
            "title": "Initial Capital",
            "type": "number"
          },
          "percents": {
            "default": 20.0,
            "description": "Target percentage per traded symbol (same semantics as PercentCapitalStrategy)",
            "exclusiveMinimum": 0,
            "maximum": 100,
            "title": "Percents",
            "type": "number"
          },
          "max_positions": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of non-auxiliary positions allowed, None for unlimited",
            "title": "Max Positions"
          },
          "sweep_symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional symbol used as cash sweep destination",
            "title": "Sweep Symbol"
          },
          "min_sweep_cash": {
            "default": 1000.0,
            "description": "Minimum idle cash required before placing a sweep order",
            "minimum": 0,
            "title": "Min Sweep Cash",
            "type": "number"
          },
          "max_sweep_percent": {
            "default": 99.0,
            "description": "Upper bound for sweep target allocation to keep a cash safety buffer",
            "exclusiveMinimum": 0,
            "maximum": 100,
            "title": "Max Sweep Percent",
            "type": "number"
          }
        },
        "title": "CashSweepPercentCapitalStrategyParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 4,
        "types": [
          {
            "name": "cash",
            "type": "float"
          },
          {
            "name": "total_value",
            "type": "float"
          },
          {
            "name": "data",
            "type": "Any"
          },
          {
            "name": "broker",
            "type": "Any"
          }
        ]
      },
      "outputs": {
        "type": "float"
      },
      "capabilities": {
        "allocation_mode": "target_percent",
        "target_weight_compatible": false,
        "atomic_complete_vector_compatible": false,
        "audited_target_weight_override": false
      }
    },
    {
      "type": "FixedInvestmentStrategy",
      "class_name": "FixedInvestmentStrategy",
      "name": "定期定投资金策略，支持年度和月度定投",
      "description": "",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for FixedInvestmentStrategy.",
        "properties": {
          "initial_capital": {
            "default": 100000.0,
            "description": "Initial capital amount",
            "exclusiveMinimum": 0,
            "title": "Initial Capital",
            "type": "number"
          },
          "investment_amount": {
            "default": 10000.0,
            "description": "Amount to invest periodically",
            "exclusiveMinimum": 0,
            "title": "Investment Amount",
            "type": "number"
          },
          "investment_frequency": {
            "default": "y",
            "description": "Investment frequency: 'y' for yearly, 'm' for monthly",
            "enum": [
              "y",
              "m"
            ],
            "title": "Investment Frequency",
            "type": "string"
          },
          "percents": {
            "default": 20.0,
            "description": "Maximum percentage per position",
            "exclusiveMinimum": 0,
            "maximum": 100,
            "title": "Percents",
            "type": "number"
          },
          "fund_val_start": {
            "default": 100.0,
            "description": "Initial fund value",
            "exclusiveMinimum": 0,
            "title": "Fund Val Start",
            "type": "number"
          },
          "max_positions": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of positions allowed, None for unlimited",
            "title": "Max Positions"
          }
        },
        "title": "FixedInvestmentStrategyParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 4,
        "types": [
          {
            "name": "cash",
            "type": "float"
          },
          {
            "name": "total_value",
            "type": "float"
          },
          {
            "name": "data",
            "type": "Any"
          },
          {
            "name": "broker",
            "type": "Any"
          }
        ]
      },
      "outputs": {
        "type": "float"
      },
      "capabilities": {
        "allocation_mode": "cash_based",
        "target_weight_compatible": true,
        "atomic_complete_vector_compatible": false,
        "audited_target_weight_override": true
      }
    },
    {
      "type": "PercentCapitalStrategy",
      "class_name": "PercentCapitalStrategy",
      "name": "百分比资金分配策略",
      "description": "",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for PercentCapitalStrategy.",
        "properties": {
          "initial_capital": {
            "default": 100000.0,
            "description": "Initial capital amount",
            "exclusiveMinimum": 0,
            "title": "Initial Capital",
            "type": "number"
          },
          "percents": {
            "default": 20.0,
            "description": "Percentage of total value to allocate per position",
            "exclusiveMinimum": 0,
            "maximum": 100,
            "title": "Percents",
            "type": "number"
          },
          "max_positions": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of positions allowed, None for unlimited",
            "title": "Max Positions"
          }
        },
        "title": "PercentCapitalStrategyParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 4,
        "types": [
          {
            "name": "cash",
            "type": "float"
          },
          {
            "name": "total_value",
            "type": "float"
          },
          {
            "name": "data",
            "type": "Any"
          },
          {
            "name": "broker",
            "type": "Any"
          }
        ]
      },
      "outputs": {
        "type": "float"
      },
      "capabilities": {
        "allocation_mode": "cash_based",
        "target_weight_compatible": false,
        "atomic_complete_vector_compatible": false,
        "audited_target_weight_override": false
      }
    },
    {
      "type": "ProportionalCapitalStrategy",
      "class_name": "ProportionalCapitalStrategy",
      "name": "Proportional Capital Allocation Strategy.",
      "description": "This strategy allows setting different maximum position sizes for different symbols, making it ideal for multi-asset portfolios where different assets have different risk profiles. Key features: - Set individual maximum allocation for each symbol - Perfect for combining stable and aggressive assets - Works with \"all-in/all-out\" trading strategies (buy when signal, sell when exit) - Does NOT perform rebalancing (use RebalancingCapitalStrategy for that) Use cases: 1. Multi-asset trend following: - Large cap ETF (SPY): max 30% - Tech ETF (QQQ): max 25% - 3x Leveraged (SOXL): max 15% 2. Global diversification with risk control: - US stocks: max 40% - Emerging markets: max 20% - Commodities: max 15% 3. Crypto portfolio with different volatility: - BTC: max 50% - ETH: max 30% - Altcoins: max 10% each Comparison with other strategies: - vs PercentCapitalStrategy: That uses same % for all symbols - vs RebalancingCapitalStrategy: That maintains exact weights with rebalancing - vs FixedInvestmentStrategy: That provides periodic cash injections Example: If total portfolio = $100,000: - SPY (weight 0.3): Buy up to $30,000 - SOXL (weight 0.15): Buy up to $15,000 When sell signal comes: Close entire position (all-out)",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for ProportionalCapitalStrategy.\n\nThis strategy allows you to set different maximum position sizes for different symbols.\nUnlike PercentCapitalStrategy which uses the same percentage for all symbols,\nthis strategy lets you customize the maximum allocation for each symbol.\n\nExample:\n    {\n        \"weights\": {\n            \"SPY\": 0.30,   // Max 30% of portfolio for SPY (stable)\n            \"QQQ\": 0.25,   // Max 25% for QQQ (tech)\n            \"SOXL\": 0.15,  // Max 15% for SOXL (3x leveraged - higher risk)\n            \"TMF\": 0.20    // Max 20% for TMF (bond hedge)\n        }\n    }",
        "properties": {
          "initial_capital": {
            "default": 100000.0,
            "description": "Initial capital amount",
            "exclusiveMinimum": 0,
            "title": "Initial Capital",
            "type": "number"
          },
          "weights": {
            "additionalProperties": {
              "type": "number"
            },
            "description": "Maximum allocation weight for each symbol (e.g., {'SPY': 0.3, 'QQQ': 0.25})",
            "title": "Weights",
            "type": "object"
          }
        },
        "title": "ProportionalCapitalStrategyParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 4,
        "types": [
          {
            "name": "cash",
            "type": "float"
          },
          {
            "name": "total_value",
            "type": "float"
          },
          {
            "name": "data",
            "type": "Any"
          },
          {
            "name": "broker",
            "type": "Any"
          }
        ]
      },
      "outputs": {
        "type": "float"
      },
      "capabilities": {
        "allocation_mode": "cash_based",
        "target_weight_compatible": false,
        "atomic_complete_vector_compatible": false,
        "audited_target_weight_override": false
      }
    },
    {
      "type": "RebalancingCapitalStrategy",
      "class_name": "RebalancingCapitalStrategy",
      "name": "Rebalancing Capital Allocation Strategy.",
      "description": "This strategy is specifically designed to work with rebalancing strategies (like TargetWeightStrategy) that include target_weight information in their signals. Key features: - Reads target weights directly from trading signals - Projects normalized Cross-sectional model weights to configured gross exposure - Calculates capital needed to reach target allocation - Preserves final executable target weights in signal feeds and persistence Design philosophy: - Trading strategy (signal) decides WHAT and WHEN to trade - Capital strategy (this) decides HOW MUCH to allocate - Trade construction decides relative weights - Capital strategy decides invested exposure and retained cash Example usage: For HFEA strategy (55% UPRO + 45% TMF): - TargetWeightStrategy generates final target_weight signals - RebalancingCapitalStrategy reads target_weight from signal - Calculates how much capital needed to reach that weight Comparison with other strategies: - PercentCapitalStrategy: Uses fixed % of cash, no target weight - FixedInvestmentStrategy: Periodic cash injection, signals have weights - RebalancingCapitalStrategy: Reads weights from signals dynamically",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for RebalancingCapitalStrategy.\n\nThis strategy reads target weights directly from trading signals and can\nreserve an explicit cash buffer for normalized Cross-sectional vectors.",
        "properties": {
          "initial_capital": {
            "default": 100000.0,
            "description": "Initial capital amount",
            "exclusiveMinimum": 0,
            "title": "Initial Capital",
            "type": "number"
          },
          "gross_exposure": {
            "default": 1.0,
            "description": "Fraction of portfolio value invested by normalized Cross-sectional complete target vectors",
            "exclusiveMinimum": 0.0,
            "maximum": 1.0,
            "title": "Gross Exposure",
            "type": "number"
          }
        },
        "title": "RebalancingCapitalStrategyParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 4,
        "types": [
          {
            "name": "cash",
            "type": "float"
          },
          {
            "name": "total_value",
            "type": "float"
          },
          {
            "name": "data",
            "type": "Any"
          },
          {
            "name": "broker",
            "type": "Any"
          }
        ]
      },
      "outputs": {
        "type": "float"
      },
      "capabilities": {
        "allocation_mode": "target_weight",
        "target_weight_compatible": true,
        "atomic_complete_vector_compatible": true,
        "audited_target_weight_override": false
      }
    },
    {
      "type": "SimplePercentCapitalStrategy",
      "class_name": "SimplePercentCapitalStrategy",
      "name": "使用可用现金百分比进行资金分配的策略",
      "description": "与PercentCapitalStrategy不同，本策略基于当前可用现金而非总资产计算分配金额",
      "params": {
        "additionalProperties": false,
        "description": "Parameters for SimplePercentCapitalStrategy.",
        "properties": {
          "initial_capital": {
            "default": 100000.0,
            "description": "Initial capital amount",
            "exclusiveMinimum": 0,
            "title": "Initial Capital",
            "type": "number"
          },
          "percents": {
            "default": 20.0,
            "description": "Percentage of available cash to allocate per position",
            "exclusiveMinimum": 0,
            "maximum": 100,
            "title": "Percents",
            "type": "number"
          },
          "max_positions": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of positions allowed, None for unlimited",
            "title": "Max Positions"
          }
        },
        "title": "SimplePercentCapitalStrategyParams",
        "type": "object"
      },
      "evaluation_domain": "per_symbol",
      "output_type": "unknown",
      "inputs": {
        "count": 4,
        "types": [
          {
            "name": "cash",
            "type": "float"
          },
          {
            "name": "total_value",
            "type": "float"
          },
          {
            "name": "data",
            "type": "Any"
          },
          {
            "name": "broker",
            "type": "Any"
          }
        ]
      },
      "outputs": {
        "type": "float"
      },
      "capabilities": {
        "allocation_mode": "cash_based",
        "target_weight_compatible": false,
        "atomic_complete_vector_compatible": false,
        "audited_target_weight_override": false
      }
    }
  ],
  "market_indicators": {
    "published_indices": [
      {
        "code": "000001.SH",
        "name": "上证综指"
      },
      {
        "code": "000300.SH",
        "name": "沪深300"
      },
      {
        "code": "000905.SH",
        "name": "中证500"
      },
      {
        "code": "399001.SZ",
        "name": "深证成指"
      },
      {
        "code": "399006.SZ",
        "name": "创业板指"
      },
      {
        "code": "SPX",
        "name": "标普500指数"
      },
      {
        "code": "IXIC",
        "name": "纳斯达克指数"
      },
      {
        "code": "VIX",
        "name": "波动率指数"
      },
      {
        "code": "NDX",
        "name": "纳斯达克100指数"
      },
      {
        "code": "DJIA",
        "name": "道琼斯工业指数"
      },
      {
        "code": "DJI",
        "name": "道琼斯指数"
      },
      {
        "code": "RUT",
        "name": "罗素2000指数"
      },
      {
        "code": "HSI",
        "name": "恒生指数"
      },
      {
        "code": "GDAXI",
        "name": "德国DAX指数"
      },
      {
        "code": "N225",
        "name": "日经225指数"
      },
      {
        "code": "KS11",
        "name": "韩国综合指数"
      },
      {
        "code": "AS51",
        "name": "澳大利亚标普200指数"
      },
      {
        "code": "SENSEX",
        "name": "印度孟买SENSEX指数"
      },
      {
        "code": "BTC_MVRV_ZSCORE",
        "name": "BTC_MVRV_ZSCORE"
      },
      {
        "code": "BTC_NVT",
        "name": "BTC_NVT"
      }
    ],
    "data_shape": "OHLCV",
    "recommended_fields": [
      "Open",
      "High",
      "Low",
      "Close",
      "Volume"
    ]
  }
}
