""" Composable Indicator System. Provides a framework for building DAGs of data transformation pipelines that process time-series data incrementally. Indicators can consume DataSources or other Indicators as inputs, composing into arbitrarily complex processing graphs. Key Components: --------------- Indicator (base.py): Abstract base class for all indicator implementations. Declares input/output schemas and implements synchronous compute(). IndicatorRegistry (registry.py): Central catalog of available indicators with rich metadata for AI agent discovery and tool generation. Pipeline (pipeline.py): Execution engine that builds DAGs, resolves dependencies, and orchestrates incremental data flow through indicator chains. Schema Types (schema.py): Type definitions for input/output schemas, computation context, and metadata for AI-native documentation. Usage Example: -------------- from indicator import Indicator, IndicatorRegistry, Pipeline from indicator.schema import ( InputSchema, OutputSchema, ComputeContext, ComputeResult, IndicatorMetadata, IndicatorParameter ) # Define an indicator class SimpleMovingAverage(Indicator): @classmethod def get_metadata(cls): return IndicatorMetadata( name="SMA", display_name="Simple Moving Average", description="Arithmetic mean of prices over N periods", category="trend", parameters=[ IndicatorParameter( name="period", type="int", description="Number of periods to average", default=20, min_value=1 ) ], tags=["moving-average", "trend-following"] ) @classmethod def get_input_schema(cls): return InputSchema( required_columns=[ ColumnInfo(name="close", type="float", description="Closing price") ] ) @classmethod def get_output_schema(cls, **params): return OutputSchema( columns=[ ColumnInfo( name="sma", type="float", description=f"Simple moving average over {params.get('period', 20)} periods" ) ] ) def compute(self, context: ComputeContext) -> ComputeResult: period = self.params["period"] closes = context.get_column("close") times = context.get_times() sma_values = [] for i in range(len(closes)): if i < period - 1: sma_values.append(None) else: window = closes[i - period + 1 : i + 1] sma_values.append(sum(window) / period) return ComputeResult( data=[ {"time": times[i], "sma": sma_values[i]} for i in range(len(times)) ] ) # Register the indicator registry = IndicatorRegistry() registry.register(SimpleMovingAverage) # Create a pipeline pipeline = Pipeline(datasource_registry) pipeline.add_datasource("price_data", "ccxt", "BTC/USD", "1D") sma_indicator = registry.create_instance("SMA", "sma_20", period=20) pipeline.add_indicator("sma_20", sma_indicator, input_node_ids=["price_data"]) # Execute results = pipeline.execute(datasource_data={"price_data": price_bars}) sma_output = results["sma_20"] # Contains columns: time, close, sma_20_sma Design Philosophy: ------------------ 1. **Schema-based composition**: Indicators declare inputs/outputs via schemas, enabling automatic validation and flexible composition. 2. **Synchronous execution**: All computation is synchronous for simplicity. Async handling happens at the event/strategy layer. 3. **Incremental updates**: Indicators receive context about what changed, allowing optimized recomputation of only affected values. 4. **AI-native metadata**: Rich descriptions, use cases, and parameter specs make indicators discoverable and usable by AI agents. 5. **Generic data flow**: Indicators work with any data source that matches their input schema, not specific DataSource instances. 6. **Event-driven**: Designed to react to DataSource updates and propagate changes through the DAG efficiently. """ from .base import DataSourceAdapter, Indicator from .pipeline import Pipeline, PipelineNode from .registry import IndicatorRegistry from .schema import ( ComputeContext, ComputeResult, IndicatorMetadata, IndicatorParameter, InputSchema, OutputSchema, ) from .talib_adapter import ( TALibIndicator, register_all_talib_indicators, is_talib_available, get_talib_version, ) from .custom_indicators import ( register_custom_indicators, CUSTOM_INDICATORS, ) __all__ = [ # Core classes "Indicator", "IndicatorRegistry", "Pipeline", "PipelineNode", "DataSourceAdapter", # Schema types "InputSchema", "OutputSchema", "ComputeContext", "ComputeResult", "IndicatorMetadata", "IndicatorParameter", # TA-Lib integration "TALibIndicator", "register_all_talib_indicators", "is_talib_available", "get_talib_version", # Custom indicators "register_custom_indicators", "CUSTOM_INDICATORS", ]