Covariance CUSUM — The Structural Alarm
Think of a building equipped with sensors on several floors. Each sensor observes movement over a different time horizon. Normal movement creates a familiar pattern of background vibration. The structural alarm is interested in sustained departures from that familiar pattern rather than in predicting every individual oscillation or identifying one attractive price level.

The program establishes its reference from an older calibration window. For each selected horizon, it estimates a historical center and a typical fluctuation scale. That baseline is held fixed while a more recent monitoring window is examined. This separation matters because continuously adapting the reference to every disturbance could hide the very structural change the alarm is supposed to detect.

Recent observations are replayed chronologically. Each horizon reading is compared with its baseline and expressed relative to its own background scale. The program combines the resulting squared departures into an energy reading. It then accumulates unusually high energy while allowing ordinary observations to reduce the accumulated evidence toward zero.

This accumulated evidence is the alarm state. One modest disturbance need not trigger a trade, while a succession of unusual readings can build a stronger case that the market environment has changed. The implementation examines a whitened energy summary related to changes in second moment behavior. It does not estimate and invert a complete moving covariance matrix for every observation.

An alarm still needs a directional interpretation. The program maintains a separate, decaying summary of signed recent returns. A sufficiently strong alarm combined with a positive directional summary supports buying. A negative directional summary supports selling. High structural activity without a clear direction does not provide the same trading instruction.

When accumulated evidence falls back toward an ordinary level, positions can be closed. An opposing directional alarm can also prompt the strategy to exit an existing position before considering another entry. Price protection, bounded position sizing, profit objectives, and a maximum holding period operate independently of the alarm calculation.

Diagnostic functions examine current standardized energy, the duration of uninterrupted elevated activity, and dispersion in the historical horizon centers. These help explain whether an alarm reflects one sudden event, a longer disturbance, or a baseline that already differs across horizons.

The building metaphor should not imply a proven early warning system. Horizon observations overlap and can be dependent. The alarm thresholds have not been calibrated to a guaranteed false alarm rate or detection delay. A strong alarm establishes that recent behavior looks unusual under its chosen reference; it does not establish that a profitable directional move must follow.

Code
// Independent model 06: chronological multihorizon covariance-energy CUSUM.
#include <default.c>

var CSPrice[130];
var CSBaseline[3];
var CSScale[3];
var CSAccumulator = 0.;
var CSDrift = 0.;
int CSLags[3] = {1, 4, 16};

int CSLocateBreak()
{
    int T, J;
    var Feature, Standard, Energy, WeightedDirection, R;
    CSAccumulator = 0.;
    CSDrift = 0.;
    for (T = 0; T < 130; T++)
    {
        if (!(CSPrice[T] > 0.))
        {
            return 0;
        }
    }
    for (J = 0; J < 3; J++)
    {
        CSBaseline[J] = 0.;
        CSScale[J] = 0.;
        // Frozen calibration window is older than the monitored window.
        for (T = 65; T <= 96; T++)
        {
            CSBaseline[J] += log(CSPrice[T] / CSPrice[T + CSLags[J]]) / sqrt(CSLags[J]) / 32.;
        }
        for (T = 65; T <= 96; T++)
        {
            Feature = log(CSPrice[T] / CSPrice[T + CSLags[J]]) / sqrt(CSLags[J]);
            CSScale[J] += (Feature - CSBaseline[J]) * (Feature - CSBaseline[J]) / 32.;
        }
        if (CSScale[J] < 1.e-20)
        {
            return 0;
        }
    }
    WeightedDirection = 0.;
    for (T = 64; T >= 0; T--)
    {
        Energy = 0.;
        for (J = 0; J < 3; J++)
        {
            Feature = log(CSPrice[T] / CSPrice[T + CSLags[J]]) / sqrt(CSLags[J]);
            Standard = (Feature - CSBaseline[J]) / sqrt(CSScale[J]);
            Energy += min(100., Standard * Standard) / 3.;
        }
        // One-sided change detector for the trace of whitened second moments.
        CSAccumulator = max(0., CSAccumulator + Energy - 1.25);
        R = log(CSPrice[T] / CSPrice[T + 1]);
        WeightedDirection = 0.85 * WeightedDirection + R;
    }
    CSDrift = WeightedDirection / sqrt(CSScale[0]);
    if (CSAccumulator < 10. || abs(CSDrift) < 1.)
    {
        return 0;
    }
    if (CSDrift > 0.)
    {
        return 1;
    }
    return -1;
}

void CSSelfTest()
{
    int T, Trouble;
    Trouble = 0;
    for (T = 0; T < 130; T++)
    {
        CSPrice[T] = 1.;
    }
    if (CSLocateBreak() != 0)
    {
        Trouble++;
    }
    for (T = 0; T < 130; T++)
    {
        CSPrice[T] = exp(0.001 * sin(0.63 * T));
    }
    CSPrice[0] = exp(0.03);
    if (CSLocateBreak() != 1)
    {
        Trouble++;
    }
    for (T = 0; T < 130; T++)
    {
        CSPrice[T] = 1. / CSPrice[T];
    }
    if (CSLocateBreak() != -1)
    {
        Trouble++;
    }
    CSPrice[20] = -1.;
    if (CSLocateBreak() != 0)
    {
        Trouble++;
    }
    file_write("Log/TS06_CovarianceCUSUM_test.txt", strf("4 checks; %d failures\n", Trouble), 0);
}

var CSWhitenedEnergy(int Offset)
{
    int J;
    var Feature, Z, Energy;
    Energy = 0.;
    if (Offset < 0 || Offset > 96)
    {
        return 0.;
    }
    for (J = 0; J < 3; J++)
    {
        if (CSScale[J] <= 0.)
        {
            return 0.;
        }
        Feature = log(CSPrice[Offset] / CSPrice[Offset + CSLags[J]]) / sqrt(CSLags[J]);
        Z = (Feature - CSBaseline[J]) / sqrt(CSScale[J]);
        Energy += Z * Z / 3.;
    }
    return Energy;
}
int CSAlarmDuration()
{
    int Offset, Duration;
    Duration = 0;
    for (Offset = 0; Offset < 64; Offset++)
    {
        if (CSWhitenedEnergy(Offset) < 1.25)
        {
            break;
        }
        Duration++;
    }
    return Duration;
}
var CSMultiHorizonDispersion()
{
    int J;
    var Z, Average, Sum;
    Average = 0.;
    Sum = 0.;
    for (J = 0; J < 3; J++)
    {
        Average += CSBaseline[J] / 3.;
    }
    for (J = 0; J < 3; J++)
    {
        Z = CSBaseline[J] - Average;
        Sum += Z * Z / 3.;
    }
    return sqrt(Sum);
}
void CSResearchDiagnostics()
{
    printf("\nCUSUM %.6g; current energy %.6g; alarm duration %d; baseline dispersion %.6g",
           CSAccumulator, CSWhitenedEnergy(0), CSAlarmDuration(), CSMultiHorizonDispersion());
}

// ============================================================================
// EXTENDED REGRESSION SUITE: deterministic properties over market regimes
// These functions run ONLY under STX_SELFTEST; they never place orders.
// ============================================================================
int CSExtendedCount = 0;
int CSExtendedFailures = 0;
void CSExpect(int Passed, string Description)
{
    CSExtendedCount++;
    if (!Passed)
    {
        CSExtendedFailures++;
        file_append("Log/TS06_CovarianceCUSUM_extended.txt", strf("FAIL: %s\n", Description));
    }
}

void CSCase_quiet_cycle()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.0005 * sin(0.17 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "quiet_cycle: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "quiet_cycle: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "quiet_cycle: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "quiet_cycle: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "quiet_cycle: missing price rejected");
}

void CSCase_mixed_cycles()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.003 * sin(0.23 * K) + 0.0007 * cos(0.81 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "mixed_cycles: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "mixed_cycles: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "mixed_cycles: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "mixed_cycles: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "mixed_cycles: missing price rejected");
}

void CSCase_persistent_upward()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(-0.001 * K + 0.0001 * sin(0.53 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "persistent_upward: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "persistent_upward: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "persistent_upward: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "persistent_upward: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "persistent_upward: missing price rejected");
}

void CSCase_persistent_downward()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.001 * K + 0.0001 * cos(0.47 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "persistent_downward: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "persistent_downward: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "persistent_downward: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "persistent_downward: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "persistent_downward: missing price rejected");
}

void CSCase_slow_curve()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.004 * cos(0.08 * K) + 0.0002 * sin(0.7 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "slow_curve: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "slow_curve: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "slow_curve: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "slow_curve: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "slow_curve: missing price rejected");
}

void CSCase_rough_curve()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.001 * sin(1.7 * K) + 0.0005 * cos(2.3 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "rough_curve: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "rough_curve: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "rough_curve: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "rough_curve: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "rough_curve: missing price rejected");
}

void CSCase_accelerating_path()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(-0.0001 * K - 0.000002 * K * K + 0.0002 * sin(0.41 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "accelerating_path: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "accelerating_path: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "accelerating_path: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "accelerating_path: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "accelerating_path: missing price rejected");
}

void CSCase_decelerating_path()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(-0.0008 * K + 0.000002 * K * K + 0.0002 * cos(0.31 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "decelerating_path: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "decelerating_path: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "decelerating_path: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "decelerating_path: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "decelerating_path: missing price rejected");
}

void CSCase_volatility_ramp()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp((0.0001 + K * 0.00001) * sin(0.37 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "volatility_ramp: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "volatility_ramp: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "volatility_ramp: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "volatility_ramp: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "volatility_ramp: missing price rejected");
}

void CSCase_volatility_decay()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.006 * exp(-0.02 * K) * cos(0.7 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "volatility_decay: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "volatility_decay: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "volatility_decay: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "volatility_decay: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "volatility_decay: missing price rejected");
}

void CSCase_cycle_with_drift()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(-0.0002 * K + 0.003 * sin(0.19 * K) + 0.0005 * cos(0.61 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "cycle_with_drift: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "cycle_with_drift: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "cycle_with_drift: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "cycle_with_drift: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "cycle_with_drift: missing price rejected");
}

void CSCase_near_zero_prices()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 0.0001 * exp(0.002 * sin(0.29 * K) + 0.001 * cos(0.13 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "near_zero_prices: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "near_zero_prices: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "near_zero_prices: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "near_zero_prices: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "near_zero_prices: missing price rejected");
}

void CSCase_large_price_units()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 10000.0 * exp(0.003 * sin(0.11 * K) + 0.0008 * cos(0.43 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "large_price_units: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "large_price_units: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "large_price_units: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "large_price_units: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "large_price_units: missing price rejected");
}

void CSCase_high_frequency_chop()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.0008 * cos(2.8 * K) + 0.001 * sin(0.23 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "high_frequency_chop: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "high_frequency_chop: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "high_frequency_chop: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "high_frequency_chop: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "high_frequency_chop: missing price rejected");
}

void CSCase_long_wave_trend()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(-0.0005 * K + 0.002 * cos(0.07 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "long_wave_trend: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "long_wave_trend: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "long_wave_trend: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "long_wave_trend: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "long_wave_trend: missing price rejected");
}

void CSCase_opposing_scales()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.005 * sin(0.09 * K) - 0.002 * sin(0.59 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "opposing_scales: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "opposing_scales: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "opposing_scales: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "opposing_scales: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "opposing_scales: missing price rejected");
}

void CSCase_nonlinear_curve()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.002 * sin(0.021 * K * K) + 0.001 * cos(0.33 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "nonlinear_curve: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "nonlinear_curve: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "nonlinear_curve: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "nonlinear_curve: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "nonlinear_curve: missing price rejected");
}

void CSCase_amplitude_modulation()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.002 * sin(0.3 * K) * cos(0.04 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "amplitude_modulation: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "amplitude_modulation: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "amplitude_modulation: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "amplitude_modulation: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "amplitude_modulation: missing price rejected");
}

void CSCase_decaying_event()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.01 * exp(-0.2 * K) + 0.0003 * sin(0.71 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "decaying_event: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "decaying_event: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "decaying_event: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "decaying_event: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "decaying_event: missing price rejected");
}

void CSCase_time_varying_frequency()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.002 * cos(0.004 * K * K + 0.11 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "time_varying_frequency: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "time_varying_frequency: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "time_varying_frequency: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "time_varying_frequency: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "time_varying_frequency: missing price rejected");
}

void CSCase_slow_fast_cancellation()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1.0 * exp(0.004 * sin(0.07 * K) + 0.0013 * cos(0.97 * K));
    }
    Original = CSLocateBreak();
    CSExpect(Original >= -1 && Original <= 1, "slow_fast_cancellation: bounded direction");
    Again = CSLocateBreak();
    CSExpect(Again == Original, "slow_fast_cancellation: repeatable estimate");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] *= 7.;
    }
    Scaled = CSLocateBreak();
    CSExpect(Scaled == Original, "slow_fast_cancellation: price-unit invariance");
    for (K = 0; K < 130; K++)
    {
        CSPrice[K] = 1. / CSPrice[K];
    }
    Reflected = CSLocateBreak();
    CSExpect(Reflected == -Original, "slow_fast_cancellation: directional reflection");
    CSPrice[65] = 0.;
    CSExpect(CSLocateBreak() == 0, "slow_fast_cancellation: missing price rejected");
}

void CSExtendedTests()
{
    CSExtendedCount = 0;
    CSExtendedFailures = 0;
    file_write("Log/TS06_CovarianceCUSUM_extended.txt",
               "TS06_CovarianceCUSUM: extended properties\n", 0);
    CSCase_quiet_cycle();
    CSCase_mixed_cycles();
    CSCase_persistent_upward();
    CSCase_persistent_downward();
    CSCase_slow_curve();
    CSCase_rough_curve();
    CSCase_accelerating_path();
    CSCase_decelerating_path();
    CSCase_volatility_ramp();
    CSCase_volatility_decay();
    CSCase_cycle_with_drift();
    CSCase_near_zero_prices();
    CSCase_large_price_units();
    CSCase_high_frequency_chop();
    CSCase_long_wave_trend();
    CSCase_opposing_scales();
    CSCase_nonlinear_curve();
    CSCase_amplitude_modulation();
    CSCase_decaying_event();
    CSCase_time_varying_frequency();
    CSCase_slow_fast_cancellation();
    file_append("Log/TS06_CovarianceCUSUM_extended.txt",
                strf("RESULT: %d checks; %d failures\n", CSExtendedCount, CSExtendedFailures));
}

function run()
{
#ifdef STX_SELFTEST
    if (is(INITRUN))
    {
        CSSelfTest();
        CSExtendedTests();
        quit("CUSUM tests complete");
    }
    return;
#endif
    int T, ChangeSide;
    var Quantity, WorstLoss;
    BarPeriod = 60;
    StartDate = 20240101;
    EndDate = 20241231;
    LookBack = 131;
    Capital = 10000.;
    Hedge = 0;
    MaxLong = 1;
    MaxShort = 1;
    if (!asset("EUR/USD"))
    {
        return;
    }
    algo("CS06");
    if (is(EXITRUN))
    {
        CSResearchDiagnostics();
        return;
    }
    if (is(LOOKBACK))
    {
        return;
    }
    for (T = 0; T < 130; T++)
    {
        CSPrice[T] = priceClose(T + 1);
    }
    ChangeSide = CSLocateBreak();
    if (CSAccumulator < 2.)
    {
        exitLong();
        exitShort();
    }
    if (ChangeSide > 0)
    {
        exitShort();
    }
    if (ChangeSide < 0)
    {
        exitLong();
    }
    if (ChangeSide == 0 || NumOpenLong + NumOpenShort > 0)
    {
        return;
    }
    if (PIPCost <= 0. || PIP <= 0. || LotAmount <= 0. || MarginCost <= 0.)
    {
        return;
    }
    if (Balance <= 0. || Equity < Balance * 0.85)
    {
        return;
    }
    Stop = max(40. * PIP, CSPrice[0] * sqrt(CSScale[0]) * 3.);
    TakeProfit = Stop * 2.;
    LifeTime = 12;
    WorstLoss = PIPCost * (Stop + Spread) / PIP + Commission * LotAmount / 10000.;
    if (WorstLoss <= 0.)
    {
        return;
    }
    Quantity = min(2000. / LotAmount, Balance * 0.005 / WorstLoss);
    Quantity = min(Quantity, max(0., Equity - MarginVal) * 0.8 / MarginCost);
    if (Quantity < 1.)
    {
        return;
    }
    Lots = floor(Quantity);
    Margin = 0.;
    Risk = 0.;
    if (ChangeSide == 1)
    {
        enterLong();
    }
    else
    {
        enterShort();
    }
}