349 lines
8.7 KiB
ReStructuredText
349 lines
8.7 KiB
ReStructuredText
Trading Factors
|
|
===============
|
|
|
|
Factors are reusable trading indicators and signals that agents can unlock and use in their analysis.
|
|
|
|
Overview
|
|
--------
|
|
|
|
Types of Factors
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
* **Basic Factors**: Simple indicators available to all agents
|
|
* **Advanced Factors**: Complex indicators requiring unlock
|
|
* **Custom Factors**: User-created indicators
|
|
|
|
Factor System Architecture
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: text
|
|
|
|
Factor Store
|
|
│
|
|
├── Basic Factors (free)
|
|
│ ├── Simple Moving Average
|
|
│ ├── RSI
|
|
│ └── MACD
|
|
│
|
|
└── Advanced Factors (locked)
|
|
├── Bollinger Bands
|
|
├── Fibonacci Retracement
|
|
├── Ichimoku Cloud
|
|
└── Machine Learning Factors
|
|
|
|
Using Factors
|
|
-------------
|
|
|
|
Basic Factors
|
|
~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.factor.basic import MovingAverageFactor
|
|
|
|
# Create factor
|
|
ma_factor = MovingAverageFactor(period=20)
|
|
|
|
# Calculate signal
|
|
result = ma_factor.calculate("AAPL")
|
|
print(f"Signal: {result.signal}")
|
|
print(f"Value: {result.value}")
|
|
|
|
Advanced Factors
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.factor.advanced import BollingerBandsFactor
|
|
|
|
# Create advanced factor (requires unlock)
|
|
bb_factor = BollingerBandsFactor(period=20, std_dev=2.0)
|
|
|
|
result = bb_factor.calculate("AAPL")
|
|
print(f"Upper band: {result.upper_band}")
|
|
print(f"Lower band: {result.lower_band}")
|
|
print(f"Signal: {result.signal}")
|
|
|
|
Factor Store
|
|
~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.factor.store import FactorStore
|
|
|
|
# Access factor store
|
|
store = FactorStore()
|
|
|
|
# Browse available factors
|
|
factors = store.list_factors()
|
|
for factor in factors:
|
|
print(f"{factor.name}: {factor.price} credits")
|
|
|
|
# Purchase factor
|
|
if store.can_afford(agent, "bollinger_bands"):
|
|
store.purchase_factor(agent, "bollinger_bands")
|
|
print("Factor purchased successfully!")
|
|
|
|
Factor Categories
|
|
-----------------
|
|
|
|
Technical Indicators
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Trend Indicators:
|
|
|
|
* Simple Moving Average (SMA)
|
|
* Exponential Moving Average (EMA)
|
|
* Moving Average Convergence Divergence (MACD)
|
|
* Average Directional Index (ADX)
|
|
|
|
Momentum Indicators:
|
|
|
|
* Relative Strength Index (RSI)
|
|
* Stochastic Oscillator
|
|
* Commodity Channel Index (CCI)
|
|
* Rate of Change (ROC)
|
|
|
|
Volatility Indicators:
|
|
|
|
* Bollinger Bands
|
|
* Average True Range (ATR)
|
|
* Keltner Channels
|
|
* Donchian Channels
|
|
|
|
Volume Indicators:
|
|
|
|
* On-Balance Volume (OBV)
|
|
* Volume Weighted Average Price (VWAP)
|
|
* Chaikin Money Flow (CMF)
|
|
* Money Flow Index (MFI)
|
|
|
|
Statistical Factors
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
* Z-Score
|
|
* Percentile Rank
|
|
* Correlation
|
|
* Cointegration
|
|
|
|
Machine Learning Factors
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
* Trend Prediction
|
|
* Volatility Forecasting
|
|
* Regime Detection
|
|
* Anomaly Detection
|
|
|
|
Creating Custom Factors
|
|
-----------------------
|
|
|
|
Basic Factor Template
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.factor.base import Factor, FactorResult
|
|
from typing import Dict, Any
|
|
|
|
class MyCustomFactor(Factor):
|
|
"""Custom factor implementation."""
|
|
|
|
def __init__(self, param1: float = 1.0, param2: int = 10):
|
|
super().__init__(
|
|
name="my_custom_factor",
|
|
description="My custom trading factor",
|
|
category="technical"
|
|
)
|
|
self.param1 = param1
|
|
self.param2 = param2
|
|
|
|
def calculate(self, symbol: str) -> FactorResult:
|
|
"""Calculate factor value."""
|
|
# Fetch data
|
|
data = self.get_data(symbol)
|
|
|
|
# Calculate factor
|
|
value = self._calculate_value(data)
|
|
|
|
# Generate signal
|
|
signal = self._generate_signal(value)
|
|
|
|
return FactorResult(
|
|
factor_name=self.name,
|
|
symbol=symbol,
|
|
value=value,
|
|
signal=signal,
|
|
timestamp=datetime.now()
|
|
)
|
|
|
|
def _calculate_value(self, data) -> float:
|
|
"""Implement factor calculation."""
|
|
# Your calculation logic here
|
|
return 0.0
|
|
|
|
def _generate_signal(self, value: float) -> str:
|
|
"""Generate trading signal from value."""
|
|
if value > 0.7:
|
|
return "strong_buy"
|
|
elif value > 0.5:
|
|
return "buy"
|
|
elif value < -0.7:
|
|
return "strong_sell"
|
|
elif value < -0.5:
|
|
return "sell"
|
|
else:
|
|
return "hold"
|
|
|
|
Advanced Factor with Parameters
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.factor.base import Factor, FactorResult
|
|
from pydantic import BaseModel
|
|
|
|
class FactorParameters(BaseModel):
|
|
"""Factor parameters."""
|
|
lookback: int = 20
|
|
threshold: float = 0.5
|
|
smoothing: bool = True
|
|
|
|
class AdvancedCustomFactor(Factor):
|
|
"""Advanced factor with configurable parameters."""
|
|
|
|
def __init__(self, params: FactorParameters = None):
|
|
super().__init__(
|
|
name="advanced_custom",
|
|
description="Advanced custom factor",
|
|
category="custom",
|
|
price=100.0 # Unlock price
|
|
)
|
|
self.params = params or FactorParameters()
|
|
|
|
def validate_params(self) -> bool:
|
|
"""Validate factor parameters."""
|
|
return (
|
|
self.params.lookback > 0 and
|
|
0 < self.params.threshold < 1
|
|
)
|
|
|
|
def calculate(self, symbol: str) -> FactorResult:
|
|
"""Calculate with error handling."""
|
|
if not self.validate_params():
|
|
raise ValueError("Invalid parameters")
|
|
|
|
try:
|
|
data = self.get_data(symbol)
|
|
value = self._complex_calculation(data)
|
|
|
|
return FactorResult(
|
|
factor_name=self.name,
|
|
symbol=symbol,
|
|
value=value,
|
|
signal=self._generate_signal(value),
|
|
metadata={
|
|
"params": self.params.dict(),
|
|
"confidence": self._calculate_confidence(data)
|
|
}
|
|
)
|
|
except Exception as e:
|
|
self.logger.error(f"Calculation error: {e}")
|
|
raise
|
|
|
|
Factor Management
|
|
-----------------
|
|
|
|
Unlocking Factors
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.factor.store import FactorStore
|
|
|
|
store = FactorStore()
|
|
|
|
# Check if agent can afford factor
|
|
if store.get_factor_price("advanced_factor") <= agent.economic_tracker.balance:
|
|
# Purchase factor
|
|
success = store.purchase_factor(agent, "advanced_factor")
|
|
if success:
|
|
print(f"Factor unlocked for {agent.agent_id}")
|
|
else:
|
|
print("Purchase failed")
|
|
else:
|
|
print("Insufficient funds")
|
|
|
|
Using Unlocked Factors
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
# Check if factor is unlocked
|
|
if agent.has_factor("bollinger_bands"):
|
|
factor = BollingerBandsFactor()
|
|
result = factor.calculate("AAPL")
|
|
|
|
# Use in analysis
|
|
signals.append(result.signal)
|
|
else:
|
|
print("Factor not unlocked")
|
|
|
|
Factor Combinations
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.factor.base import FactorCombination
|
|
|
|
# Combine multiple factors
|
|
combo = FactorCombination([
|
|
("rsi", 0.3),
|
|
("macd", 0.3),
|
|
("bollinger_bands", 0.4)
|
|
])
|
|
|
|
result = combo.calculate("AAPL")
|
|
print(f"Combined signal: {result.signal}")
|
|
print(f"Combined score: {result.score:.2f}")
|
|
|
|
Factor Performance
|
|
------------------
|
|
|
|
Backtesting Factors
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
from openclaw.backtest.engine import BacktestEngine
|
|
|
|
# Test factor performance
|
|
engine = BacktestEngine()
|
|
engine.add_factor("rsi", RSIFactor(period=14))
|
|
|
|
results = engine.run_backtest(
|
|
symbols=["AAPL", "MSFT", "GOOGL"],
|
|
start_date="2023-01-01",
|
|
end_date="2023-12-31"
|
|
)
|
|
|
|
print(f"Factor win rate: {results.win_rate:.2%}")
|
|
print(f"Average return: {results.avg_return:.2%}")
|
|
|
|
Factor Selection
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
.. code-block:: python
|
|
|
|
# Rank factors by performance
|
|
factor_scores = {}
|
|
for factor_name in agent.unlocked_factors:
|
|
factor = store.get_factor(factor_name)
|
|
score = factor.calculate_performance_score(
|
|
symbols=["AAPL", "MSFT"],
|
|
lookback_days=90
|
|
)
|
|
factor_scores[factor_name] = score
|
|
|
|
# Use top 3 factors
|
|
top_factors = sorted(factor_scores.items(), key=lambda x: x[1], reverse=True)[:3]
|