Parabolic Time Price System
Tracks price trends with dynamic stop-loss levels that accelerate with trend momentum.
Export Optimization Code
Advanced Options & Examples
Optimization Output Example
Example output from running the optimization code above on a year of S&P data.
Best Parabolic SAR parameters found:
acceleration_factor_start = 0.01
acceleration_factor_max = 0.22
acceleration_factor_step = 0.1
start_position = Short
Rating: 0.10524691358024692
Best Indicator values: [5176.85, 5176.85, 5175.6, ... ]
Analysis
The optimized Parabolic SAR parameters (AF start=0.01, AF max=0.22, AF step=0.1, starting Short) generated significantly better results compared to the default parameters (AF start=0.02, AF max=0.2, AF step=0.02, starting Long). The optimized strategy achieved a profit of $3.20 with 50 trades, while the default strategy resulted in a loss of $-10.97 with 34 trades. The lower initial acceleration factor in the optimized parameters allows the SAR to be more patient before accelerating, which reduces false signals and whipsaws, leading to better overall performance across the trading period.
Optimized Trading Simulation
- SideLONG
- Shares0.0356
- Entry$5638.94
- Value$5638.94
Default Trading Simulation
- SideSHORT
- Shares0.0327
- Entry$5983.25
- Value$5638.94
Trading Simulation Code
For those who want to run their own simulation to compare results.
fn simulate_trading(best_indicator: &[f64], high: &[f64], low: &[f64], close: &[f64]) {
println!("
--- Trading Simulation ---");
let initial_capital = 1000.0;
let mut capital = initial_capital;
let investment_pct = 0.20;
struct Trade {
entry_price: f64,
shares: f64,
position_type: Position,
}
let mut open_position: Option<Trade> = None;
// Print table header
println!(
"{:<5} | {:<19} | {:<10} | {:<10} | {:<12} | {:<15} | {:<10}",
"Day", "Event", "SAR", "Price", "Shares", "Capital", "P/L"
);
println!("{}", "-".repeat(95));
for i in 1..best_indicator.len() {
if i >= close.len() {
break;
}
let sar = best_indicator[i];
let prev_sar = best_indicator[i - 1];
let current_price = close[i];
let prev_price = close[i - 1];
let day = i;
// Detect position changes based on SAR crossovers
if let Some(trade) = open_position.take() {
// Check if we need to close and reverse position
let should_reverse = match trade.position_type {
Position::Long => current_price < sar && prev_price >= prev_sar,
Position::Short => current_price > sar && prev_price <= prev_sar,
};
if should_reverse {
// Close current position
let exit_value = match trade.position_type {
Position::Long => {
let sale_value = trade.shares * current_price;
let profit = sale_value - (trade.shares * trade.entry_price);
capital += sale_value;
println!(
"{:<5} | {:<19} | {:<10.2} | ${:<9.2} | {:<12.4} | ${:<14.2} | ${:<9.2}",
day,
"Close Long",
sar,
current_price,
trade.shares,
capital,
profit
);
profit
}
Position::Short => {
let cost_to_cover = trade.shares * current_price;
let profit = (trade.shares * trade.entry_price) - cost_to_cover;
capital += profit;
println!(
"{:<5} | {:<19} | {:<10.2} | ${:<9.2} | {:<12.4} | ${:<14.2} | ${:<9.2}",
day,
"Close Short",
sar,
current_price,
trade.shares,
capital,
profit
);
profit
}
};
// Open reverse position
let investment = capital * investment_pct;
let shares = investment / current_price;
let new_position_type = match trade.position_type {
Position::Long => {
println!(
"{:<5} | {:<19} | {:<10.2} | ${:<9.2} | {:<12.4} | ${:<14.2} | {}",
day,
"Open Short (Reverse)",
sar,
current_price,
shares,
capital,
"-"
);
Position::Short
}
Position::Short => {
capital -= investment;
println!(
"{:<5} | {:<19} | {:<10.2} | ${:<9.2} | {:<12.4} | ${:<14.2} | {}",
day,
"Open Long (Reverse)",
sar,
current_price,
shares,
capital,
"-"
);
Position::Long
}
};
open_position = Some(Trade {
entry_price: current_price,
shares,
position_type: new_position_type,
});
} else {
// Keep position open
open_position = Some(trade);
}
} else {
// No position open, check for entry signal
if prev_price <= prev_sar && current_price > sar {
// Bullish crossover - go long
let investment = capital * investment_pct;
let shares = investment / current_price;
capital -= investment;
println!(
"{:<5} | {:<19} | {:<10.2} | ${:<9.2} | {:<12.4} | ${:<14.2} | {}",
day,
"Open Long",
sar,
current_price,
shares,
capital,
"-"
);
open_position = Some(Trade {
entry_price: current_price,
shares,
position_type: Position::Long,
});
} else if prev_price >= prev_sar && current_price < sar {
// Bearish crossover - go short
let investment = capital * investment_pct;
let shares = investment / current_price;
println!(
"{:<5} | {:<19} | {:<10.2} | ${:<9.2} | {:<12.4} | ${:<14.2} | {}",
day,
"Open Short",
sar,
current_price,
shares,
capital,
"-"
);
open_position = Some(Trade {
entry_price: current_price,
shares,
position_type: Position::Short,
});
}
}
}
println!("
--- Final Results ---");
if let Some(trade) = open_position {
let last_price = close.last().unwrap_or(&0.0);
match trade.position_type {
Position::Long => {
println!("Simulation ended with an OPEN LONG position:");
println!(" - Shares: {:.4}", trade.shares);
println!(" - Entry Price: ${:.2}", trade.entry_price);
let current_value = trade.shares * last_price;
capital += current_value;
println!(
" - Position value at last price (${:.2}): ${:.2}",
last_price, current_value
);
}
Position::Short => {
println!("Simulation ended with an OPEN SHORT position:");
println!(" - Shares: {:.4}", trade.shares);
println!(" - Entry Price: ${:.2}", trade.entry_price);
let cost_to_cover = trade.shares * last_price;
let pnl = (trade.shares * trade.entry_price) - cost_to_cover;
capital += pnl;
println!(
" - Unrealized P/L at last price (${:.2}): ${:.2}",
last_price, pnl
);
}
}
}
let final_pnl = capital - initial_capital;
println!("
Initial Capital: ${:.2}", initial_capital);
println!("Final Capital: ${:.2}", capital);
println!("Total P/L: ${:.2}", final_pnl);
}
fn main() {
// Fetch data and perform optimization as shown in the optimization code above
// Run trading simulation with optimized parameters
simulate_trading(&best_indicators, &high, &low, &close);
// Compare with default parameters (typically 0.02, 0.2, 0.02, Long)
println!("
Default Indicator values for comparison:");
let default_sar = parabolic_time_price_system(&high, &low, 0.02, 0.2, 0.02, Position::Long, 0.0);
println!("{:?}", default_sar);
simulate_trading(&default_sar, &high, &low, &close);
}