Bipower Jump Fade — The Shock Absorber
Imagine the market as a vehicle moving along a road with ordinary vibration and occasional severe bumps. Ordinary vibration represents continuous price fluctuation. A severe bump represents a discontinuity that is unusually large compared with the surrounding movement. This strategy attempts to separate those two sources of activity and then considers whether an isolated bump might be followed by a partial rebound.

The program first estimates the ordinary background scale from an older window that excludes the latest possible jump. Its main tool is bipower variation, which uses neighboring absolute returns rather than relying only on squared individual returns. The purpose is to obtain a continuous movement reference that is less easily dominated by one isolated price shock.

It then examines a shorter local window, comparing ordinary realized variation with its bipower counterpart. When realized variation substantially exceeds the continuous movement proxy, the excess is interpreted as evidence that discontinuous movement may matter. The program also checks whether the newest completed return is exceptionally large relative to the historical continuous scale.

Both checks must support the shock interpretation. A large current move by itself is not enough if the local variation comparison does not agree. The preceding return must also remain below the program's jump threshold. That additional gate is intended to avoid treating a cluster of violent movements as a single temporary interruption.

The trading response is deliberately contrarian. An isolated upward shock supports a short position, and an isolated downward shock supports a long position. The program remembers the completed price immediately before the shock as an analytical anchor. If price subsequently returns to that anchor in the expected direction, the position can be closed without waiting for the full profit target.

This is a short horizon response, not a patient equilibrium strategy. Positions have a brief maximum lifetime, and the stop distance adapts partly to the estimated continuous scale. Model diagnostics include fourth power activity, truncated variation, and a count of recent unusually large moves. These describe the surrounding shock environment rather than certifying that a reversal is inevitable.

The shock absorber metaphor has an important boundary: some bumps are the beginning of a different road. News can permanently reprice an asset, and an apparently isolated jump can initiate sustained movement. The implemented thresholds are heuristic screening rules, not a calibrated statistical significance test. Fading a genuine repricing event can therefore be costly despite disciplined sizing and protective exits.

Code
// Independent model 05: realized variance, bipower variation and jump reversal.
#include <default.c>

var BVClose[100];
var BVContinuous = 0.;
var BVJumpShare = 0.;
var BVStandardJump = 0.;
var BVAnchor = 0.;

int BVDetectDiscontinuity()
{
    int K;
    var RV, BPV, LeftReturn, RightReturn, CurrentReturn, BeforeReturn;
    BVContinuous = 0.;
    BVJumpShare = 0.;
    BVStandardJump = 0.;
    for (K = 0; K < 100; K++)
    {
        if (!(BVClose[K] > 0.))
        {
            return 0;
        }
    }
    // Historical continuous scale EXCLUDES the current possible jump.
    BPV = 0.;
    for (K = 1; K <= 64; K++)
    {
        LeftReturn = log(BVClose[K] / BVClose[K + 1]);
        RightReturn = log(BVClose[K + 1] / BVClose[K + 2]);
        BPV += abs(LeftReturn) * abs(RightReturn) * 1.5707963267948966 / 64.;
    }
    if (BPV <= 1.e-20)
    {
        return 0;
    }
    BVContinuous = BPV;
    // Local 16-bar realized variation compared with its bipower counterpart.
    RV = 0.;
    BPV = 0.;
    for (K = 0; K < 16; K++)
    {
        LeftReturn = log(BVClose[K] / BVClose[K + 1]);
        RightReturn = log(BVClose[K + 1] / BVClose[K + 2]);
        RV += LeftReturn * LeftReturn;
        BPV += abs(LeftReturn) * abs(RightReturn) * 1.5707963267948966;
    }
    if (RV <= 1.e-20)
    {
        return 0;
    }
    BVJumpShare = max(0., RV - BPV) / RV;
    CurrentReturn = log(BVClose[0] / BVClose[1]);
    BeforeReturn = log(BVClose[1] / BVClose[2]);
    BVStandardJump = CurrentReturn / sqrt(BVContinuous);
    // No claim of a formal finite-sample jump-test p-value.
    if (BVJumpShare < 0.35 || abs(BVStandardJump) < 4.)
    {
        return 0;
    }
    if (abs(BeforeReturn) > 3. * sqrt(BVContinuous))
    {
        return 0;
    }
    if (CurrentReturn > 0.)
    {
        return -1;
    }
    return 1;
}

void BVRunTests()
{
    int K, Faults;
    Faults = 0;
    for (K = 0; K < 100; K++)
    {
        BVClose[K] = 1.;
    }
    if (BVDetectDiscontinuity() != 0)
    {
        Faults++;
    }
    for (K = 0; K < 100; K++)
    {
        BVClose[K] = exp(0.0001 * sin(K));
    }
    BVClose[0] = exp(0.01);
    if (BVDetectDiscontinuity() != -1)
    {
        Faults++;
    }
    for (K = 0; K < 100; K++)
    {
        BVClose[K] = 1. / BVClose[K];
    }
    if (BVDetectDiscontinuity() != 1)
    {
        Faults++;
    }
    BVClose[8] = 0.;
    if (BVDetectDiscontinuity() != 0)
    {
        Faults++;
    }
    file_write("Log/TS05_BipowerJumpFade_test.txt", strf("4 checks; %d failures\n", Faults), 0);
}

var BVQuarticity()
{
    int K;
    var R, Estimate;
    Estimate = 0.;
    for (K = 1; K <= 64; K++)
    {
        R = log(BVClose[K] / BVClose[K + 1]);
        Estimate += pow(R, 4.) / 64.;
    }
    return Estimate;
}
var BVTruncatedVariation(var SigmaMultiple)
{
    int K;
    var R, Sum, Boundary;
    if (BVContinuous <= 0. || SigmaMultiple <= 0.)
    {
        return 0.;
    }
    Boundary = SigmaMultiple * sqrt(BVContinuous);
    Sum = 0.;
    for (K = 0; K < 32; K++)
    {
        R = log(BVClose[K] / BVClose[K + 1]);
        if (abs(R) <= Boundary)
        {
            Sum += R * R / 32.;
        }
    }
    return Sum;
}
int BVRecentShockCount()
{
    int K, Count;
    var R;
    Count = 0;
    if (BVContinuous <= 0.)
    {
        return 0;
    }
    for (K = 0; K < 16; K++)
    {
        R = log(BVClose[K] / BVClose[K + 1]);
        if (abs(R) > 4. * sqrt(BVContinuous))
        {
            Count++;
        }
    }
    return Count;
}
void BVResearchDiagnostics()
{
    printf("\nBipower continuous %.6g; quarticity %.6g; truncated32 %.6g; shocks16 %d",
           BVContinuous, BVQuarticity(), BVTruncatedVariation(3.), BVRecentShockCount());
}

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

void BVCase_quiet_cycle()
{
    int K, Original, Again, Scaled, Reflected;
    for (K = 0; K < 100; K++)
    {
        BVClose[K] = 1.0 * exp(0.0005 * sin(0.17 * K));
    }
    Original = BVDetectDiscontinuity();
    BVExpect(Original >= -1 && Original <= 1, "quiet_cycle: bounded direction");
    Again = BVDetectDiscontinuity();
    BVExpect(Again == Original, "quiet_cycle: repeatable estimate");
    for (K = 0; K < 100; K++)
    {
        BVClose[K] *= 7.;
    }
    Scaled = BVDetectDiscontinuity();
    BVExpect(Scaled == Original, "quiet_cycle: price-unit invariance");
    for (K = 0; K < 100; K++)
    {
        BVClose[K] = 1. / BVClose[K];
    }
    Reflected = BVDetectDiscontinuity();
    BVExpect(Reflected == -Original, "quiet_cycle: directional reflection");
    BVClose[50] = 0.;
    BVExpect(BVDetectDiscontinuity() == 0, "quiet_cycle: missing price rejected");
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

void BVExtendedTests()
{
    BVExtendedCount = 0;
    BVExtendedFailures = 0;
    file_write("Log/TS05_BipowerJumpFade_extended.txt",
               "TS05_BipowerJumpFade: extended properties\n", 0);
    BVCase_quiet_cycle();
    BVCase_mixed_cycles();
    BVCase_persistent_upward();
    BVCase_persistent_downward();
    BVCase_slow_curve();
    BVCase_rough_curve();
    BVCase_accelerating_path();
    BVCase_decelerating_path();
    BVCase_volatility_ramp();
    BVCase_volatility_decay();
    BVCase_cycle_with_drift();
    BVCase_near_zero_prices();
    BVCase_large_price_units();
    BVCase_high_frequency_chop();
    BVCase_long_wave_trend();
    BVCase_opposing_scales();
    BVCase_nonlinear_curve();
    BVCase_amplitude_modulation();
    BVCase_decaying_event();
    BVCase_time_varying_frequency();
    BVCase_slow_fast_cancellation();
    file_append("Log/TS05_BipowerJumpFade_extended.txt",
                strf("RESULT: %d checks; %d failures\n", BVExtendedCount, BVExtendedFailures));
}

function run()
{
#ifdef STX_SELFTEST
    if (is(INITRUN))
    {
        BVRunTests();
        BVExtendedTests();
        quit("Bipower tests complete");
    }
    return;
#endif
    int K, Fade;
    var Cap, Loss;
    BarPeriod = 60;
    LookBack = 101;
    StartDate = 20240101;
    EndDate = 20241231;
    Capital = 10000.;
    Hedge = 0;
    MaxLong = 1;
    MaxShort = 1;
    if (!asset("EUR/USD"))
    {
        return;
    }
    algo("BV05");
    if (is(INITRUN))
    {
        BVAnchor = 0.;
    }
    if (is(EXITRUN))
    {
        BVResearchDiagnostics();
        return;
    }
    if (is(LOOKBACK))
    {
        return;
    }
    for (K = 0; K < 100; K++)
    {
        BVClose[K] = priceClose(K + 1);
    }
    Fade = BVDetectDiscontinuity();
    // Exit when the price has retraced to the pre-jump level.
    if (BVAnchor > 0.)
    {
        if (NumOpenLong > 0 && BVClose[0] >= BVAnchor)
        {
            exitLong();
        }
        if (NumOpenShort > 0 && BVClose[0] <= BVAnchor)
        {
            exitShort();
        }
    }
    if (Fade == 0 || NumOpenLong + NumOpenShort > 0)
    {
        return;
    }
    if (Balance <= 0. || Equity < Balance * 0.85)
    {
        return;
    }
    if (PIP <= 0. || PIPCost <= 0. || MarginCost <= 0. || LotAmount <= 0.)
    {
        return;
    }
    Stop = max(30. * PIP, BVClose[0] * sqrt(BVContinuous) * 3.);
    TakeProfit = Stop;
    LifeTime = 3;
    Loss = (Stop + Spread) * PIPCost / PIP + Commission * LotAmount / 10000.;
    if (Loss <= 0.)
    {
        return;
    }
    Cap = min(Balance * 0.005 / Loss, 2000. / LotAmount);
    Cap = min(Cap, max(0., Equity - MarginVal) * 0.8 / MarginCost);
    if (Cap < 1.)
    {
        return;
    }
    Lots = floor(Cap);
    Risk = 0.;
    Margin = 0.;
    BVAnchor = BVClose[1];
    if (Fade > 0)
    {
        enterLong();
    }
    else
    {
        enterShort();
    }
}