// 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();
}
}