// Independent model 07: GARCH variance forecast curve and compression release.
#include <default.c>
var GPrices[100];
var GForecast[16];
var GUnconditional = 0.;
var GConditional = 0.;
var GRelease = 0.;
int GProjectRisk()
{
int T, Ahead;
var R, Omega, State, Average, Current, Drift;
GRelease = 0.;
GConditional = 0.;
GUnconditional = 0.;
for (T = 0; T < 100; T++)
{
if (!(GPrices[T] > 0.))
{
return 0;
}
}
Average = 0.;
for (T = 1; T <= 80; T++)
{
R = log(GPrices[T] / GPrices[T + 1]);
Average += R * R / 80.;
}
if (Average < 1.e-20)
{
return 0;
}
// Fixed stationary coefficients: alpha=.12, beta=.86, alpha+beta=.98.
// These are model assumptions, NOT maximum-likelihood fitted parameters.
GUnconditional = Average;
Omega = Average * 0.02;
State = Average;
for (T = 80; T >= 1; T--)
{
R = log(GPrices[T] / GPrices[T + 1]);
State = Omega + 0.12 * R * R + 0.86 * State;
}
GConditional = State;
for (Ahead = 0; Ahead < 16; Ahead++)
{
GForecast[Ahead] = Average + pow(0.98, Ahead) * (State - Average);
}
// Term-structure slope must indicate low immediate risk versus distant risk.
if (GForecast[0] >= 0.8 * GForecast[15])
{
return 0;
}
Current = log(GPrices[0] / GPrices[1]);
Drift = log(GPrices[1] / GPrices[17]);
GRelease = Current / sqrt(State);
if (abs(GRelease) < 1.5 || abs(GRelease) > 4.)
{
return 0;
}
if (Current > 0. && Drift > 0.)
{
return 1;
}
if (Current < 0. && Drift < 0.)
{
return -1;
}
return 0;
}
void GExamine()
{
int T, A, B, F;
F = 0;
for (T = 0; T < 100; T++)
{
GPrices[T] = 1.;
}
if (GProjectRisk() != 0)
{
F++;
}
for (T = 0; T < 100; T++)
{
GPrices[T] = exp(0.001 * cos(0.31 * T));
}
A = GProjectRisk();
if (GConditional <= 0. || GForecast[15] <= 0.)
{
F++;
}
for (T = 0; T < 100; T++)
{
GPrices[T] = 1. / GPrices[T];
}
B = GProjectRisk();
if (A != -B)
{
F++;
}
GPrices[4] = 0.;
if (GProjectRisk() != 0)
{
F++;
}
file_write("Log/TS07_GARCHForecastCurve_test.txt", strf("4 checks; %d failures\n", F), 0);
}
var GIntegratedForecast(int Horizon)
{
int Ahead;
var Sum;
Sum = 0.;
if (Horizon < 1 || Horizon > 16)
{
return 0.;
}
for (Ahead = 0; Ahead < Horizon; Ahead++)
{
Sum += GForecast[Ahead];
}
return sqrt(max(0., Sum));
}
var GGaussianScore()
{
int T;
var R, V, LogScore;
if (GUnconditional <= 0.)
{
return 0.;
}
V = GUnconditional;
LogScore = 0.;
for (T = 64; T >= 1; T--)
{
R = log(GPrices[T] / GPrices[T + 1]);
LogScore += log(max(V, 1.e-25)) + R * R / max(V, 1.e-25);
V = 0.02 * GUnconditional + 0.12 * R * R + 0.86 * V;
}
return -LogScore / 128.;
}
var GVarianceAfterShock(var ShockSigma, int Steps)
{
int Step;
var V;
if (Steps < 1 || Steps > 64 || GConditional <= 0.)
{
return 0.;
}
V = 0.02 * GUnconditional + (0.12 * ShockSigma * ShockSigma + 0.86) * GConditional;
for (Step = 1; Step < Steps; Step++)
{
V = 0.02 * GUnconditional + 0.98 * V;
}
return V;
}
void GResearchDiagnostics()
{
printf("\nGARCH forecast sigma4 %.6g; sigma16 %.6g; log-score %.6g; postshock variance %.6g",
GIntegratedForecast(4), GIntegratedForecast(16), GGaussianScore(),
GVarianceAfterShock(3., 4));
}
// ============================================================================
// EXTENDED REGRESSION SUITE: deterministic properties over market regimes
// These functions run ONLY under STX_SELFTEST; they never place orders.
// ============================================================================
int GExtendedCount = 0;
int GExtendedFailures = 0;
void GExpect(int Passed, string Description)
{
GExtendedCount++;
if (!Passed)
{
GExtendedFailures++;
file_append("Log/TS07_GARCHForecastCurve_extended.txt", strf("FAIL: %s\n", Description));
}
}
void GCase_quiet_cycle()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.0005 * sin(0.17 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "quiet_cycle: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "quiet_cycle: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "quiet_cycle: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "quiet_cycle: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "quiet_cycle: missing price rejected");
}
void GCase_mixed_cycles()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.003 * sin(0.23 * K) + 0.0007 * cos(0.81 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "mixed_cycles: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "mixed_cycles: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "mixed_cycles: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "mixed_cycles: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "mixed_cycles: missing price rejected");
}
void GCase_persistent_upward()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(-0.001 * K + 0.0001 * sin(0.53 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "persistent_upward: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "persistent_upward: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "persistent_upward: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "persistent_upward: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "persistent_upward: missing price rejected");
}
void GCase_persistent_downward()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.001 * K + 0.0001 * cos(0.47 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "persistent_downward: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "persistent_downward: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "persistent_downward: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "persistent_downward: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "persistent_downward: missing price rejected");
}
void GCase_slow_curve()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.004 * cos(0.08 * K) + 0.0002 * sin(0.7 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "slow_curve: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "slow_curve: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "slow_curve: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "slow_curve: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "slow_curve: missing price rejected");
}
void GCase_rough_curve()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.001 * sin(1.7 * K) + 0.0005 * cos(2.3 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "rough_curve: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "rough_curve: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "rough_curve: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "rough_curve: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "rough_curve: missing price rejected");
}
void GCase_accelerating_path()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(-0.0001 * K - 0.000002 * K * K + 0.0002 * sin(0.41 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "accelerating_path: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "accelerating_path: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "accelerating_path: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "accelerating_path: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "accelerating_path: missing price rejected");
}
void GCase_decelerating_path()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(-0.0008 * K + 0.000002 * K * K + 0.0002 * cos(0.31 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "decelerating_path: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "decelerating_path: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "decelerating_path: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "decelerating_path: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "decelerating_path: missing price rejected");
}
void GCase_volatility_ramp()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp((0.0001 + K * 0.00001) * sin(0.37 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "volatility_ramp: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "volatility_ramp: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "volatility_ramp: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "volatility_ramp: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "volatility_ramp: missing price rejected");
}
void GCase_volatility_decay()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.006 * exp(-0.02 * K) * cos(0.7 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "volatility_decay: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "volatility_decay: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "volatility_decay: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "volatility_decay: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "volatility_decay: missing price rejected");
}
void GCase_cycle_with_drift()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(-0.0002 * K + 0.003 * sin(0.19 * K) + 0.0005 * cos(0.61 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "cycle_with_drift: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "cycle_with_drift: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "cycle_with_drift: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "cycle_with_drift: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "cycle_with_drift: missing price rejected");
}
void GCase_near_zero_prices()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 0.0001 * exp(0.002 * sin(0.29 * K) + 0.001 * cos(0.13 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "near_zero_prices: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "near_zero_prices: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "near_zero_prices: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "near_zero_prices: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "near_zero_prices: missing price rejected");
}
void GCase_large_price_units()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 10000.0 * exp(0.003 * sin(0.11 * K) + 0.0008 * cos(0.43 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "large_price_units: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "large_price_units: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "large_price_units: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "large_price_units: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "large_price_units: missing price rejected");
}
void GCase_high_frequency_chop()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.0008 * cos(2.8 * K) + 0.001 * sin(0.23 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "high_frequency_chop: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "high_frequency_chop: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "high_frequency_chop: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "high_frequency_chop: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "high_frequency_chop: missing price rejected");
}
void GCase_long_wave_trend()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(-0.0005 * K + 0.002 * cos(0.07 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "long_wave_trend: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "long_wave_trend: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "long_wave_trend: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "long_wave_trend: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "long_wave_trend: missing price rejected");
}
void GCase_opposing_scales()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.005 * sin(0.09 * K) - 0.002 * sin(0.59 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "opposing_scales: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "opposing_scales: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "opposing_scales: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "opposing_scales: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "opposing_scales: missing price rejected");
}
void GCase_nonlinear_curve()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.002 * sin(0.021 * K * K) + 0.001 * cos(0.33 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "nonlinear_curve: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "nonlinear_curve: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "nonlinear_curve: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "nonlinear_curve: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "nonlinear_curve: missing price rejected");
}
void GCase_amplitude_modulation()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.002 * sin(0.3 * K) * cos(0.04 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "amplitude_modulation: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "amplitude_modulation: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "amplitude_modulation: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "amplitude_modulation: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "amplitude_modulation: missing price rejected");
}
void GCase_decaying_event()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.01 * exp(-0.2 * K) + 0.0003 * sin(0.71 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "decaying_event: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "decaying_event: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "decaying_event: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "decaying_event: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "decaying_event: missing price rejected");
}
void GCase_time_varying_frequency()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.002 * cos(0.004 * K * K + 0.11 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "time_varying_frequency: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "time_varying_frequency: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "time_varying_frequency: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "time_varying_frequency: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "time_varying_frequency: missing price rejected");
}
void GCase_slow_fast_cancellation()
{
int K, Original, Again, Scaled, Reflected;
for (K = 0; K < 100; K++)
{
GPrices[K] = 1.0 * exp(0.004 * sin(0.07 * K) + 0.0013 * cos(0.97 * K));
}
Original = GProjectRisk();
GExpect(Original >= -1 && Original <= 1, "slow_fast_cancellation: bounded direction");
Again = GProjectRisk();
GExpect(Again == Original, "slow_fast_cancellation: repeatable estimate");
for (K = 0; K < 100; K++)
{
GPrices[K] *= 7.;
}
Scaled = GProjectRisk();
GExpect(Scaled == Original, "slow_fast_cancellation: price-unit invariance");
for (K = 0; K < 100; K++)
{
GPrices[K] = 1. / GPrices[K];
}
Reflected = GProjectRisk();
GExpect(Reflected == -Original, "slow_fast_cancellation: directional reflection");
GPrices[50] = 0.;
GExpect(GProjectRisk() == 0, "slow_fast_cancellation: missing price rejected");
}
void GExtendedTests()
{
GExtendedCount = 0;
GExtendedFailures = 0;
file_write("Log/TS07_GARCHForecastCurve_extended.txt",
"TS07_GARCHForecastCurve: extended properties\n", 0);
GCase_quiet_cycle();
GCase_mixed_cycles();
GCase_persistent_upward();
GCase_persistent_downward();
GCase_slow_curve();
GCase_rough_curve();
GCase_accelerating_path();
GCase_decelerating_path();
GCase_volatility_ramp();
GCase_volatility_decay();
GCase_cycle_with_drift();
GCase_near_zero_prices();
GCase_large_price_units();
GCase_high_frequency_chop();
GCase_long_wave_trend();
GCase_opposing_scales();
GCase_nonlinear_curve();
GCase_amplitude_modulation();
GCase_decaying_event();
GCase_time_varying_frequency();
GCase_slow_fast_cancellation();
file_append("Log/TS07_GARCHForecastCurve_extended.txt",
strf("RESULT: %d checks; %d failures\n", GExtendedCount, GExtendedFailures));
}
function run()
{
#ifdef STX_SELFTEST
if (is(INITRUN))
{
GExamine();
GExtendedTests();
quit("GARCH tests complete");
}
return;
#endif
int T, Expansion;
var SizeLimit, Damage;
BarPeriod = 60;
LookBack = 101;
StartDate = 20240101;
EndDate = 20241231;
Capital = 10000.;
MaxLong = 1;
MaxShort = 1;
Hedge = 0;
if (!asset("EUR/USD"))
{
return;
}
algo("G07");
if (is(EXITRUN))
{
GResearchDiagnostics();
return;
}
if (is(LOOKBACK))
{
return;
}
for (T = 0; T < 100; T++)
{
GPrices[T] = priceClose(T + 1);
}
Expansion = GProjectRisk();
// Exit after the predicted compression has become an elevated-risk regime.
if (GUnconditional > 0. && GConditional > 1.8 * GUnconditional)
{
exitLong();
exitShort();
}
if (Expansion == 0 || NumOpenLong + NumOpenShort > 0)
{
return;
}
if (Balance <= 0. || Equity < Balance * 0.85)
{
return;
}
if (PIP <= 0. || PIPCost <= 0. || LotAmount <= 0. || MarginCost <= 0.)
{
return;
}
Stop = max(30. * PIP, GPrices[0] * sqrt(GForecast[3]) * 2.5);
TakeProfit = Stop * 3.;
LifeTime = 20;
Damage = (Stop + Spread) / PIP * PIPCost + Commission * LotAmount / 10000.;
if (Damage <= 0.)
{
return;
}
SizeLimit = min(Balance * 0.005 / Damage, 2000. / LotAmount);
SizeLimit = min(SizeLimit, max(0., Equity - MarginVal) * 0.8 / MarginCost);
if (SizeLimit < 1.)
{
return;
}
Risk = 0.;
Margin = 0.;
Lots = floor(SizeLimit);
if (Expansion > 0)
{
enterLong();
}
else
{
enterShort();
}
}