MMAR/config.py
2026-05-03 21:24:14 +00:00

224 lines
8.1 KiB
Python

"""
Configuration file for MMAR Volatility Forecasting Model
Based on: "Volatility Forecasting with the Multifractal Model of Asset Returns" (Zhang, 2017)
"""
import numpy as np
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
# =============================================================================
# DATA PARAMETERS
# =============================================================================
# Symbol and timeframe
SYMBOL = "EURUSD"
TIMEFRAME_MT5 = "M5" # MT5 timeframe code: M1, M5, M10, M15, M30, H1, H4, D1
TIMEFRAME_MINUTES = 5 # For internal calculations (1 min = 1)
# Date range for historical data (training period)
START_DATE = "2024-08-03"
END_DATE = "2026-03-01"
# Forecast parameters
FORECAST_DAYS = 25 # Number of days to forecast
FORECAST_INTERVAL_MINUTES = TIMEFRAME_MINUTES # Keep forecast units aligned with loaded bars
FORECAST_LENGTH = int(FORECAST_DAYS * (24 * 60) / TIMEFRAME_MINUTES) # Match actual forecast horizon
TRADING_DAYS_PER_YEAR = 252
# MetaTrader 5 Settings
MT5_ENABLED = True # Set to False to use CSV files only
MT5_LOGIN = None # Set your MT5 login (None = use current terminal)
MT5_PASSWORD = "" # Leave empty if already logged in
MT5_SERVER = "" # Leave empty if already connected
# =============================================================================
# STEP 1: PARTITION FUNCTION PARAMETERS
# =============================================================================
# Delta t range for partition function (in NUMBER OF OBSERVATIONS)
# Zhang used values spaced by factor of 1.1, from ~400s to 9000s
# For 1-minute data: 400s = 7 obs, 9000s = 150 obs
DELTA_T_MIN = 1 # Minimum number of observations per interval
DELTA_T_MAX = 150 # Maximum number of observations per interval
DELTA_T_SPACING_FACTOR = 1.1 # Logarithmic spacing
NUM_DELTA_T_VALUES = 30 # Number of delta_t values to test
# q values for moment scaling analysis
# Paper used q from 0.01 to 30.00
Q_MIN = 0.01
Q_MAX = 30.0
Q_STEP = 0.5 # Step size for q values
# Linearity threshold (R-squared for partition plots)
# Paper achieved average R² of 0.66
MIN_R_SQUARED = 0.60 # Minimum R² to consider scaling behavior valid
# =============================================================================
# STEP 2: SCALING FUNCTION PARAMETERS
# =============================================================================
# Number of discrete q values for scaling function estimation
NUM_Q_VALUES = 60
# =============================================================================
# STEP 3: MULTIFRACTAL SPECTRUM PARAMETERS
# =============================================================================
# Grid search parameters for fitting spectrum to distributions
ALPHA_0_MIN = 0.1
ALPHA_0_MAX = 1.0
ALPHA_0_STEP = 0.01
# For binomial distribution
ALPHA_MIN_RANGE = (0.01, 0.5)
ALPHA_MAX_RANGE = (0.5, 2.0)
ALPHA_GRID_STEP = 0.01
# For gamma distribution
GAMMA_MIN = 0.1
GAMMA_MAX = 10.0
GAMMA_STEP = 0.1
# =============================================================================
# STEP 4-6: CASCADE AND FBM PARAMETERS
# =============================================================================
# Multiplicative cascade parameters for standalone Step 4/5 artifacts
CASCADE_B = 2 # Binary cascade (divide into 2 intervals at each step)
CASCADE_K_MAX = 10 # Standalone cascade depth (2^10 = 1024 intervals)
# FBM generation parameters
FBM_METHOD = "cholesky" # Method for generating FBM: 'cholesky' or 'fft'
# =============================================================================
# STEP 7: MONTE CARLO SIMULATION PARAMETERS
# =============================================================================
# Number of Monte Carlo simulations
NUM_SIMULATIONS = 1000 # Paper used 10,000
# Random seed for reproducibility
RANDOM_SEED = 42
# =============================================================================
# OUTPUT PARAMETERS
# =============================================================================
# Directory for saving results
OUTPUT_DIR = BASE_DIR / "results"
# Directory for saving plots
PLOT_DIR = BASE_DIR / "plots"
# Directory for data
DATA_DIR = BASE_DIR / "data"
# Verbose output
VERBOSE = True
# Save intermediate results
SAVE_INTERMEDIATE = True
# =============================================================================
# HELPER FUNCTIONS
# =============================================================================
def generate_q_values():
"""Generate array of q values for partition function."""
return np.arange(Q_MIN, Q_MAX + Q_STEP, Q_STEP)
def generate_delta_t_values():
"""
Generate array of delta t values with logarithmic spacing.
Returns values in NUMBER OF OBSERVATIONS (not seconds or minutes).
For 1-minute data, delta_t=60 means 60 one-minute returns = 1 hour.
Returns:
--------
np.ndarray
Array of delta_t values (integers, number of observations)
"""
delta_t_values = []
current = DELTA_T_MIN
while current <= DELTA_T_MAX:
delta_t_values.append(int(current))
current *= DELTA_T_SPACING_FACTOR
# Remove duplicates and sort
return np.unique(np.array(delta_t_values))
def periods_per_day():
"""Return the number of forecast intervals in a 24-hour day."""
return (24 * 60) / FORECAST_INTERVAL_MINUTES
def periods_per_year():
"""Return the annualization factor for the configured forecast interval."""
return periods_per_day() * TRADING_DAYS_PER_YEAR
def daily_window_size():
"""Return the nearest whole-number rolling window for one day."""
return max(1, int(round(periods_per_day())))
def interval_label(minutes=None):
"""Return a short display label for an interval length in minutes."""
minutes = FORECAST_INTERVAL_MINUTES if minutes is None else minutes
if minutes < 60:
return f"{minutes:g}-min"
hours = minutes / 60
return f"{hours:g}-hour"
def get_trading_hours_filter():
"""
Return function to filter trading hours.
For EURUSD (24h FX market), we use full day without filtering.
Note: Seasonality filtering has been removed as we test without it first.
"""
def filter_func(hour, minute):
# Allow full 24h trading day
return True
return filter_func
# =============================================================================
# VALIDATION
# =============================================================================
def validate_config():
"""Validate configuration parameters."""
assert DELTA_T_MIN > 0, "DELTA_T_MIN must be positive"
assert DELTA_T_MAX > DELTA_T_MIN, "DELTA_T_MAX must be greater than DELTA_T_MIN"
assert Q_MIN > 0, "Q_MIN must be positive"
assert Q_MAX > Q_MIN, "Q_MAX must be greater than Q_MIN"
assert 0 <= MIN_R_SQUARED <= 1, "MIN_R_SQUARED must be between 0 and 1"
assert TIMEFRAME_MINUTES > 0, "TIMEFRAME_MINUTES must be positive"
assert FORECAST_INTERVAL_MINUTES > 0, "FORECAST_INTERVAL_MINUTES must be positive"
assert FORECAST_LENGTH > 0, "FORECAST_LENGTH must be positive"
assert FORECAST_INTERVAL_MINUTES == TIMEFRAME_MINUTES, (
"FORECAST_INTERVAL_MINUTES should match TIMEFRAME_MINUTES so forecasts, "
"realized volatility, and annualization use the same return interval"
)
assert NUM_SIMULATIONS > 0, "NUM_SIMULATIONS must be positive"
assert CASCADE_B >= 2, "CASCADE_B must be at least 2"
assert CASCADE_K_MAX > 0, "CASCADE_K_MAX must be positive"
print("✓ Configuration validated successfully")
if __name__ == "__main__":
validate_config()
print(f"\nMMar Forecast Configuration")
print(f"=" * 50)
print(f"Symbol: {SYMBOL}")
print(f"Period: {START_DATE} to {END_DATE}")
print(f"Forecast: {FORECAST_DAYS} days ahead")
print(f"Forecast interval: {FORECAST_INTERVAL_MINUTES} minutes")
print(f"Forecast simulation length: {FORECAST_LENGTH} returns")
print(f"Monte Carlo simulations: {NUM_SIMULATIONS}")
print(f"\nΔt range: {DELTA_T_MIN}s to {DELTA_T_MAX}s")
print(f"q range: {Q_MIN} to {Q_MAX}")
print(f"Number of q values: {len(generate_q_values())}")
print(f"Number of Δt values: {len(generate_delta_t_values())}")