FinancialAnalysisParameters.java

package com.morphiqlabs.wavelet.cwt.finance;

/**
 * Configurable parameters for financial wavelet analysis.
 * 
 * <p>This class provides a fluent builder interface to customize all thresholds
 * and parameters used in financial analysis. It replaces the static constants
 * in FinancialAnalysisConfig to allow per-analysis customization.</p>
 * 
 * <p>Example usage:</p>
 * <pre>{@code
 * FinancialAnalysisParameters params = FinancialAnalysisParameters.builder()
 *     .crashAsymmetryThreshold(15.0)  // More sensitive crash detection
 *     .volatilityLowThreshold(0.3)    // Tighter volatility bands
 *     .regimeTrendThreshold(0.03)     // 3% trend threshold
 *     .annualRiskFreeRate(0.045)      // 4.5% annual risk-free rate
 *     .build();
 * 
 * FinancialWaveletAnalyzer analyzer = new FinancialWaveletAnalyzer(params);
 * }</pre>
 */
public final class FinancialAnalysisParameters {
    
    /**
     * Standard number of trading days per year.
     * This is the conventional value used in financial markets for annualization.
     */
    public static final int TRADING_DAYS_PER_YEAR = 252;
    
    // Crash Detection Parameters
    private final double crashAsymmetryThreshold;
    private final double crashMinScale;
    private final double crashMaxScale;
    private final int crashNumScales;
    
    // Volatility Analysis Parameters
    private final double volatilityLowThreshold;
    private final double volatilityMediumThreshold;
    private final double volatilityHighThreshold;
    private final double volumeDivergenceThreshold;
    private final double priceDivergenceThreshold;
    
    // Cyclical Analysis Parameters
    private final double[] cycleTestFrequencies;
    
    // Trend Analysis Parameters
    private final double trendMinScale;
    private final double trendMaxScale;
    private final int trendNumScales;
    
    // Market Regime Detection Parameters
    private final int regimeDetectionLookbackPeriod;
    private final double regimeTrendThreshold;
    
    // Trading Signal Generation Parameters
    private final int signalGenerationMinHistory;
    private final int recentCrashLookbackWindow;
    private final double crashProbabilityNormalization;
    private final int riskAssessmentCrashWindow;
    private final int crashPredictionForwardWindow;
    
    // Technical Analysis Parameters
    private final int supportResistanceWindow;
    
    // Risk Assessment Parameters
    private final double defaultAverageVolatility;
    private final double baseRiskLevel;
    private final double annualRiskFreeRate;
    
    // Optimization Parameters
    private final OptimizationParameters optimization;
    
    /**
     * Private constructor - use builder to create instances.
     */
    private FinancialAnalysisParameters(Builder builder) {
        this.crashAsymmetryThreshold = builder.crashAsymmetryThreshold;
        this.crashMinScale = builder.crashMinScale;
        this.crashMaxScale = builder.crashMaxScale;
        this.crashNumScales = builder.crashNumScales;
        
        this.volatilityLowThreshold = builder.volatilityLowThreshold;
        this.volatilityMediumThreshold = builder.volatilityMediumThreshold;
        this.volatilityHighThreshold = builder.volatilityHighThreshold;
        this.volumeDivergenceThreshold = builder.volumeDivergenceThreshold;
        this.priceDivergenceThreshold = builder.priceDivergenceThreshold;
        
        this.cycleTestFrequencies = builder.cycleTestFrequencies.clone();
        
        this.trendMinScale = builder.trendMinScale;
        this.trendMaxScale = builder.trendMaxScale;
        this.trendNumScales = builder.trendNumScales;
        
        this.regimeDetectionLookbackPeriod = builder.regimeDetectionLookbackPeriod;
        this.regimeTrendThreshold = builder.regimeTrendThreshold;
        
        this.signalGenerationMinHistory = builder.signalGenerationMinHistory;
        this.recentCrashLookbackWindow = builder.recentCrashLookbackWindow;
        this.crashProbabilityNormalization = builder.crashProbabilityNormalization;
        this.riskAssessmentCrashWindow = builder.riskAssessmentCrashWindow;
        this.crashPredictionForwardWindow = builder.crashPredictionForwardWindow;
        
        this.supportResistanceWindow = builder.supportResistanceWindow;
        
        this.defaultAverageVolatility = builder.defaultAverageVolatility;
        this.baseRiskLevel = builder.baseRiskLevel;
        this.annualRiskFreeRate = builder.annualRiskFreeRate;
        
        this.optimization = builder.optimization.build();
    }
    
    /**
     * Creates a new builder with default values from FinancialAnalysisConfig.
     */
    public static Builder builder() {
        return new Builder();
    }
    
    /**
     * Creates default parameters matching the static configuration.
     */
    public static FinancialAnalysisParameters defaultParameters() {
        return builder().build();
    }
    
    // Getters
    public double getCrashAsymmetryThreshold() { return crashAsymmetryThreshold; }
    public double getCrashMinScale() { return crashMinScale; }
    public double getCrashMaxScale() { return crashMaxScale; }
    public int getCrashNumScales() { return crashNumScales; }
    
    public double getVolatilityLowThreshold() { return volatilityLowThreshold; }
    public double getVolatilityMediumThreshold() { return volatilityMediumThreshold; }
    public double getVolatilityHighThreshold() { return volatilityHighThreshold; }
    public double getVolumeDivergenceThreshold() { return volumeDivergenceThreshold; }
    public double getPriceDivergenceThreshold() { return priceDivergenceThreshold; }
    
    public double[] getCycleTestFrequencies() { return cycleTestFrequencies.clone(); }
    
    public double getTrendMinScale() { return trendMinScale; }
    public double getTrendMaxScale() { return trendMaxScale; }
    public int getTrendNumScales() { return trendNumScales; }
    
    public int getRegimeDetectionLookbackPeriod() { return regimeDetectionLookbackPeriod; }
    public double getRegimeTrendThreshold() { return regimeTrendThreshold; }
    
    public int getSignalGenerationMinHistory() { return signalGenerationMinHistory; }
    public int getRecentCrashLookbackWindow() { return recentCrashLookbackWindow; }
    public double getCrashProbabilityNormalization() { return crashProbabilityNormalization; }
    public int getRiskAssessmentCrashWindow() { return riskAssessmentCrashWindow; }
    public int getCrashPredictionForwardWindow() { return crashPredictionForwardWindow; }
    
    public int getSupportResistanceWindow() { return supportResistanceWindow; }
    
    public double getDefaultAverageVolatility() { return defaultAverageVolatility; }
    public double getBaseRiskLevel() { return baseRiskLevel; }
    public double getAnnualRiskFreeRate() { return annualRiskFreeRate; }
    
    public OptimizationParameters getOptimization() { return optimization; }
    
    /**
     * Builder for FinancialAnalysisParameters.
     */
    public static final class Builder {
        // Initialize with defaults
        private double crashAsymmetryThreshold = 10.0;
        private double crashMinScale = 1.0;
        private double crashMaxScale = 10.0;
        private int crashNumScales = 20;
        
        private double volatilityLowThreshold = 0.5;
        private double volatilityMediumThreshold = 1.5;
        private double volatilityHighThreshold = 3.0;
        private double volumeDivergenceThreshold = 2.0;
        private double priceDivergenceThreshold = 0.01;
        
        private double[] cycleTestFrequencies = {0.2, 0.1, 0.045, 0.02};
        
        private double trendMinScale = 10.0;
        private double trendMaxScale = 50.0;
        private int trendNumScales = 10;
        
        private int regimeDetectionLookbackPeriod = 20;
        private double regimeTrendThreshold = 0.05;
        
        private int signalGenerationMinHistory = 20;
        private int recentCrashLookbackWindow = 20;
        private double crashProbabilityNormalization = 20.0;
        private int riskAssessmentCrashWindow = 20;
        private int crashPredictionForwardWindow = 5;
        
        private int supportResistanceWindow = 20;
        
        private double defaultAverageVolatility = 0.02;
        private double baseRiskLevel = 0.5;
        private double annualRiskFreeRate = 0.03; // Default 3% annual risk-free rate
        
        private OptimizationParameters.Builder optimization = OptimizationParameters.builder();
        
        // Crash Detection setters
        public Builder crashAsymmetryThreshold(double threshold) {
            if (threshold <= 0) {
                throw new IllegalArgumentException("Crash asymmetry threshold must be positive");
            }
            this.crashAsymmetryThreshold = threshold;
            return this;
        }
        
        public Builder crashScaleRange(double minScale, double maxScale, int numScales) {
            if (minScale <= 0 || maxScale <= minScale) {
                throw new IllegalArgumentException("Invalid scale range");
            }
            if (numScales <= 0) {
                throw new IllegalArgumentException("Number of scales must be positive");
            }
            this.crashMinScale = minScale;
            this.crashMaxScale = maxScale;
            this.crashNumScales = numScales;
            return this;
        }
        
        // Volatility Analysis setters
        public Builder volatilityThresholds(double low, double medium, double high) {
            if (low <= 0 || medium <= low || high <= medium) {
                throw new IllegalArgumentException("Volatility thresholds must be positive and increasing");
            }
            this.volatilityLowThreshold = low;
            this.volatilityMediumThreshold = medium;
            this.volatilityHighThreshold = high;
            return this;
        }
        
        public Builder volatilityLowThreshold(double threshold) {
            if (threshold <= 0) {
                throw new IllegalArgumentException("Volatility threshold must be positive");
            }
            this.volatilityLowThreshold = threshold;
            return this;
        }
        
        public Builder volumeDivergenceThreshold(double threshold) {
            if (threshold <= 0) {
                throw new IllegalArgumentException("Volume divergence threshold must be positive");
            }
            this.volumeDivergenceThreshold = threshold;
            return this;
        }
        
        public Builder priceDivergenceThreshold(double threshold) {
            if (threshold <= 0) {
                throw new IllegalArgumentException("Price divergence threshold must be positive");
            }
            this.priceDivergenceThreshold = threshold;
            return this;
        }
        
        // Cyclical Analysis setters
        public Builder cycleTestFrequencies(double... frequencies) {
            if (frequencies == null || frequencies.length == 0) {
                throw new IllegalArgumentException("Cycle test frequencies cannot be empty");
            }
            for (double freq : frequencies) {
                if (freq <= 0 || freq >= 1) {
                    throw new IllegalArgumentException("Frequencies must be between 0 and 1");
                }
            }
            this.cycleTestFrequencies = frequencies.clone();
            return this;
        }
        
        // Trend Analysis setters
        public Builder trendScaleRange(double minScale, double maxScale, int numScales) {
            if (minScale <= 0 || maxScale <= minScale) {
                throw new IllegalArgumentException("Invalid scale range");
            }
            if (numScales <= 0) {
                throw new IllegalArgumentException("Number of scales must be positive");
            }
            this.trendMinScale = minScale;
            this.trendMaxScale = maxScale;
            this.trendNumScales = numScales;
            return this;
        }
        
        // Market Regime setters
        public Builder regimeDetectionLookbackPeriod(int period) {
            if (period <= 0) {
                throw new IllegalArgumentException("Lookback period must be positive");
            }
            this.regimeDetectionLookbackPeriod = period;
            return this;
        }
        
        public Builder regimeTrendThreshold(double threshold) {
            if (threshold <= 0) {
                throw new IllegalArgumentException("Regime trend threshold must be positive");
            }
            this.regimeTrendThreshold = threshold;
            return this;
        }
        
        // Trading Signal setters
        public Builder signalGenerationMinHistory(int minHistory) {
            if (minHistory <= 0) {
                throw new IllegalArgumentException("Minimum history must be positive");
            }
            this.signalGenerationMinHistory = minHistory;
            return this;
        }
        
        public Builder recentCrashLookbackWindow(int window) {
            if (window <= 0) {
                throw new IllegalArgumentException("Lookback window must be positive");
            }
            this.recentCrashLookbackWindow = window;
            return this;
        }
        
        public Builder crashProbabilityNormalization(double normalization) {
            if (normalization <= 0) {
                throw new IllegalArgumentException("Normalization factor must be positive");
            }
            this.crashProbabilityNormalization = normalization;
            return this;
        }
        
        // Technical Analysis setters
        public Builder supportResistanceWindow(int window) {
            if (window <= 0) {
                throw new IllegalArgumentException("Support/resistance window must be positive");
            }
            this.supportResistanceWindow = window;
            return this;
        }
        
        // Risk Assessment setters
        public Builder defaultAverageVolatility(double volatility) {
            if (volatility <= 0) {
                throw new IllegalArgumentException("Average volatility must be positive");
            }
            this.defaultAverageVolatility = volatility;
            return this;
        }
        
        public Builder baseRiskLevel(double risk) {
            if (risk < 0 || risk > 1) {
                throw new IllegalArgumentException("Base risk level must be between 0 and 1");
            }
            this.baseRiskLevel = risk;
            return this;
        }
        
        public Builder annualRiskFreeRate(double rate) {
            if (rate < 0) {
                throw new IllegalArgumentException("Risk-free rate cannot be negative");
            }
            this.annualRiskFreeRate = rate;
            return this;
        }
        
        // Optimization parameters
        public Builder withOptimization(OptimizationParameters optimization) {
            if (optimization == null) {
                throw new IllegalArgumentException("Optimization parameters cannot be null");
            }
            this.optimization = OptimizationParameters.builder(optimization);
            return this;
        }
        
        public Builder optimizationBuilder(OptimizationParameters.Builder builder) {
            if (builder == null) {
                throw new IllegalArgumentException("Optimization builder cannot be null");
            }
            this.optimization = builder;
            return this;
        }
        
        public FinancialAnalysisParameters build() {
            return new FinancialAnalysisParameters(this);
        }
    }
}