258 lines
10 KiB
Plaintext
258 lines
10 KiB
Plaintext
import pandas as pd
|
||
import numpy as np
|
||
from typing import Dict, Tuple
|
||
import matplotlib.pyplot as plt
|
||
|
||
class MultiAssetRCDDAnalyzer:
|
||
"""
|
||
Enhance DOLPHIN with multi-asset RCDD analysis for better correlation weighting
|
||
"""
|
||
|
||
def __init__(self, rcdd_analyzer):
|
||
self.rcdd_analyzer = rcdd_analyzer
|
||
|
||
def compute_drawdown_correlations(self,
|
||
price_data: pd.DataFrame,
|
||
entry_prices: Dict[str, float]) -> pd.DataFrame:
|
||
"""
|
||
Compute correlations between assets based on their RCDD characteristics
|
||
"""
|
||
rcdd_metrics = {}
|
||
|
||
# Calculate RCDD for each asset
|
||
for asset in price_data.columns:
|
||
if asset in entry_prices:
|
||
metrics = self.rcdd_analyzer.recursive_conditional_drawdown(
|
||
price_data[asset], entry_prices[asset]
|
||
)
|
||
rcdd_metrics[asset] = {
|
||
'avg_drawdown': metrics.avg_drawdown,
|
||
'max_drawdown': metrics.max_drawdown,
|
||
'recovery_probability': metrics.recovery_probability,
|
||
'recovery_time': metrics.avg_recovery_time,
|
||
'confidence_width': metrics.confidence_interval[1] - metrics.confidence_interval[0]
|
||
}
|
||
|
||
# Create DataFrame of RCDD characteristics
|
||
rcdd_df = pd.DataFrame(rcdd_metrics).T
|
||
|
||
# Compute correlations between RCDD characteristics
|
||
correlations = {}
|
||
|
||
for char in rcdd_df.columns:
|
||
corr_matrix = rcdd_df[[char]].corrwith(rcdd_df, axis=0)
|
||
correlations[f'{char}_correlation'] = corr_matrix
|
||
|
||
return pd.DataFrame(correlations)
|
||
|
||
def enhanced_pair_weighting(self,
|
||
asset1: str,
|
||
asset2: str,
|
||
price_data: pd.DataFrame,
|
||
entry_prices: Dict[str, float]) -> Dict:
|
||
"""
|
||
Enhanced weighting that combines price correlation with RCDD analysis
|
||
"""
|
||
# Traditional price correlation
|
||
price_corr = price_data[asset1].corr(price_data[asset2])
|
||
|
||
# RCDD-based analysis
|
||
metrics1 = self.rcdd_analyzer.recursive_conditional_drawdown(
|
||
price_data[asset1], entry_prices[asset1]
|
||
)
|
||
metrics2 = self.rcdd_analyzer.recursive_conditional_drawdown(
|
||
price_data[asset2], entry_prices[asset2]
|
||
)
|
||
|
||
# Drawdown behavior similarity
|
||
dd_similarity = 1 - abs(metrics1.avg_drawdown - metrics2.avg_drawdown) / \
|
||
max(metrics1.avg_drawdown, metrics2.avg_drawdown, 0.01)
|
||
|
||
recovery_similarity = 1 - abs(metrics1.recovery_probability - metrics2.recovery_probability)
|
||
|
||
# Confidence reliability
|
||
conf_width1 = metrics1.confidence_interval[1] - metrics1.confidence_interval[0]
|
||
conf_width2 = metrics2.confidence_interval[1] - metrics2.confidence_interval[0]
|
||
|
||
# Lower confidence width = more reliable
|
||
reliability1 = 1 / (1 + conf_width1)
|
||
reliability2 = 1 / (1 + conf_width2)
|
||
combined_reliability = (reliability1 + reliability2) / 2
|
||
|
||
# Enhanced weighting formula
|
||
# Independence factor (lower correlation = higher weight)
|
||
independence_factor = 1 - abs(price_corr)
|
||
|
||
# Behavior diversity factor (different RCDD behavior = higher weight)
|
||
diversity_factor = 1 - (dd_similarity + recovery_similarity) / 2
|
||
|
||
# Reliability factor (more reliable RCDD = higher weight)
|
||
|
||
# Combined weight
|
||
enhanced_weight = (independence_factor * 0.4 +
|
||
diversity_factor * 0.3 +
|
||
combined_reliability * 0.3)
|
||
|
||
return {
|
||
'price_correlation': price_corr,
|
||
'drawdown_similarity': dd_similarity,
|
||
'recovery_similarity': recovery_similarity,
|
||
'combined_reliability': combined_reliability,
|
||
'independence_factor': independence_factor,
|
||
'diversity_factor': diversity_factor,
|
||
'enhanced_weight': enhanced_weight,
|
||
'traditional_weight': independence_factor, # For comparison
|
||
'weight_improvement': enhanced_weight - independence_factor
|
||
}
|
||
|
||
def demonstrate_concept():
|
||
"""
|
||
Demonstrate how multi-asset RCDD analysis enhances DOLPHIN weighting
|
||
"""
|
||
print("🐬 MULTI-ASSET RCDD ENHANCEMENT FOR DOLPHIN")
|
||
print("="*55)
|
||
|
||
# Create sample data with different correlation and RCDD patterns
|
||
np.random.seed(42)
|
||
dates = pd.date_range('2023-01-01', periods=200, freq='1H')
|
||
|
||
# Simulate different asset types
|
||
assets = {
|
||
'BTC': {'base_price': 50000, 'volatility': 0.03, 'trend': 0.001},
|
||
'ETH': {'base_price': 3000, 'volatility': 0.035, 'trend': 0.0012}, # Similar to BTC
|
||
'GOLD': {'base_price': 2000, 'volatility': 0.015, 'trend': 0.0002}, # Different behavior
|
||
'SPY': {'base_price': 400, 'volatility': 0.02, 'trend': 0.0008}, # Different again
|
||
'BONDS': {'base_price': 100, 'volatility': 0.008, 'trend': -0.0001} # Very different
|
||
}
|
||
|
||
price_data = {}
|
||
entry_prices = {}
|
||
|
||
for asset, params in assets.items():
|
||
returns = np.random.normal(params['trend'], params['volatility'], len(dates))
|
||
|
||
# Add some correlation between BTC and ETH
|
||
if asset == 'ETH':
|
||
btc_returns = np.array(list(price_data.values())[0]) if price_data else returns
|
||
returns = 0.7 * returns + 0.3 * np.random.normal(0, 0.01, len(dates))
|
||
|
||
prices = params['base_price'] * np.exp(np.cumsum(returns))
|
||
price_data[asset] = prices
|
||
entry_prices[asset] = prices[50] # Entry point after some history
|
||
|
||
price_df = pd.DataFrame(price_data, index=dates)
|
||
|
||
print("📊 Sample Data Created:")
|
||
print(f"Assets: {list(price_df.columns)}")
|
||
print(f"Entry points: {entry_prices}")
|
||
|
||
# Simulate basic RCDD analyzer for demo
|
||
class MockRCDDAnalyzer:
|
||
def recursive_conditional_drawdown(self, price_series, entry_price):
|
||
from dataclasses import dataclass
|
||
|
||
@dataclass
|
||
class MockMetrics:
|
||
avg_drawdown: float
|
||
max_drawdown: float
|
||
recovery_probability: float
|
||
avg_recovery_time: float
|
||
confidence_interval: Tuple[float, float]
|
||
|
||
# Simulate RCDD metrics based on price characteristics
|
||
volatility = price_series.pct_change().std()
|
||
recent_drawdown = max(0, entry_price - price_series.min())
|
||
|
||
return MockMetrics(
|
||
avg_drawdown=recent_drawdown * 0.7,
|
||
max_drawdown=recent_drawdown,
|
||
recovery_probability=max(0.3, min(0.9, 1 - volatility * 10)),
|
||
avg_recovery_time=volatility * 100,
|
||
confidence_interval=(recent_drawdown * 0.5, recent_drawdown * 1.2)
|
||
)
|
||
|
||
# Initialize analyzer
|
||
mock_rcdd = MockRCDDAnalyzer()
|
||
multi_asset_analyzer = MultiAssetRCDDAnalyzer(mock_rcdd)
|
||
|
||
print("\n🔍 ANALYZING ASSET PAIRS:")
|
||
print("="*40)
|
||
|
||
# Analyze key pairs
|
||
test_pairs = [
|
||
('BTC', 'ETH'), # High price correlation, similar RCDD
|
||
('BTC', 'GOLD'), # Low price correlation, different RCDD
|
||
('BTC', 'BONDS'), # Very different everything
|
||
('ETH', 'SPY'), # Medium correlation, different RCDD
|
||
]
|
||
|
||
results = []
|
||
|
||
for asset1, asset2 in test_pairs:
|
||
analysis = multi_asset_analyzer.enhanced_pair_weighting(
|
||
asset1, asset2, price_df, entry_prices
|
||
)
|
||
|
||
results.append({
|
||
'pair': f'{asset1}-{asset2}',
|
||
**analysis
|
||
})
|
||
|
||
print(f"\n{asset1} vs {asset2}:")
|
||
print(f" Price Correlation: {analysis['price_correlation']:.3f}")
|
||
print(f" Drawdown Similarity: {analysis['drawdown_similarity']:.3f}")
|
||
print(f" Recovery Similarity: {analysis['recovery_similarity']:.3f}")
|
||
print(f" Combined Reliability: {analysis['combined_reliability']:.3f}")
|
||
print(f" Traditional Weight: {analysis['traditional_weight']:.3f}")
|
||
print(f" Enhanced Weight: {analysis['enhanced_weight']:.3f}")
|
||
print(f" Improvement: {analysis['weight_improvement']:+.3f}")
|
||
|
||
# Summary comparison
|
||
results_df = pd.DataFrame(results)
|
||
|
||
print(f"\n📈 WEIGHT COMPARISON SUMMARY:")
|
||
print("="*35)
|
||
print(f"Average Traditional Weight: {results_df['traditional_weight'].mean():.3f}")
|
||
print(f"Average Enhanced Weight: {results_df['enhanced_weight'].mean():.3f}")
|
||
print(f"Pairs with Improvement: {(results_df['weight_improvement'] > 0).sum()}/{len(results_df)}")
|
||
|
||
# Identify best and worst pairs
|
||
best_pair = results_df.loc[results_df['enhanced_weight'].idxmax()]
|
||
worst_pair = results_df.loc[results_df['enhanced_weight'].idxmin()]
|
||
|
||
print(f"\n🏆 HIGHEST WEIGHTED PAIR: {best_pair['pair']}")
|
||
print(f" Enhanced Weight: {best_pair['enhanced_weight']:.3f}")
|
||
print(f" Why: Independent price movement + diverse RCDD behavior")
|
||
|
||
print(f"\n⚠️ LOWEST WEIGHTED PAIR: {worst_pair['pair']}")
|
||
print(f" Enhanced Weight: {worst_pair['enhanced_weight']:.3f}")
|
||
print(f" Why: Correlated prices + similar RCDD behavior")
|
||
|
||
print(f"\n💡 KEY INSIGHTS:")
|
||
print("="*20)
|
||
print("✅ Enhanced weighting considers:")
|
||
print(" • Price correlation (independence)")
|
||
print(" • RCDD behavior diversity")
|
||
print(" • Prediction reliability")
|
||
print(" • Multi-dimensional asset relationships")
|
||
|
||
print("\n✅ Benefits for DOLPHIN:")
|
||
print(" • More nuanced pair weighting")
|
||
print(" • Better regime detection accuracy")
|
||
print(" • Reduced false signals from correlated behavior")
|
||
print(" • Adaptive to changing market structures")
|
||
|
||
print(f"\n🔧 PRACTICAL IMPLEMENTATION:")
|
||
print("="*30)
|
||
print("1. Calculate RCDD for all assets in universe")
|
||
print("2. Compute enhanced weights for all pairs")
|
||
print("3. Use enhanced weights in DOLPHIN algorithm")
|
||
print("4. Monitor weight stability over time")
|
||
print("5. Recalibrate periodically")
|
||
|
||
return results_df, price_df
|
||
|
||
# Run the demonstration
|
||
if __name__ == "__main__":
|
||
results, data = demonstrate_concept()
|