use clap::Parser;
use eyre::Result;
use simulator_client::{BacktestClient, RangeBound, filter_ranges};
#[derive(Parser, Debug, Clone)]
pub struct RangesArgs {
#[arg(
long,
env = "SIMULATOR_URL",
default_value = "simulator.termina.technology"
)]
pub url: String,
#[arg(long)]
pub after: Option<String>,
#[arg(long)]
pub before: Option<String>,
#[arg(long)]
pub json: bool,
}
pub async fn ranges(args: RangesArgs) -> Result<()> {
let after: Option<RangeBound> = args.after.as_deref().map(str::parse).transpose()?;
let before: Option<RangeBound> = args.before.as_deref().map(str::parse).transpose()?;
let client = BacktestClient::builder()
.url(format!("wss://{}/backtest", args.url))
.build();
let available = client.available_ranges().await?;
let available = filter_ranges(&available, after.as_ref(), before.as_ref());
if available.is_empty() {
if args.json {
println!("[]");
} else {
println!("No available ranges matching the given filters.");
}
return Ok(());
}
if args.json {
println!("{}", serde_json::to_string_pretty(&available)?);
return Ok(());
}
println!(
"{:<30} {:<30} {:<15} End Slot",
"Start Time (UTC)", "End Time (UTC)", "Start Slot"
);
println!("{}", "-".repeat(90));
for range in &available {
let start_time = range.bundle_start_slot_utc.as_deref().unwrap_or("-");
let end_time = range.max_bundle_end_slot_utc.as_deref().unwrap_or("-");
let end_slot = range
.max_bundle_end_slot
.map(|s| s.to_string())
.unwrap_or_else(|| "unbounded".to_string());
println!(
"{:<30} {:<30} {:<15} {}",
start_time, end_time, range.bundle_start_slot, end_slot
);
}
Ok(())
}