Skip to content

Commit 4ae7a4c

Browse files
committed
style: format futures paper files
1 parent 2c579b4 commit 4ae7a4c

4 files changed

Lines changed: 93 additions & 78 deletions

File tree

src/commands/futures_paper.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,12 @@ pub async fn run(
310310
size,
311311
price,
312312
stop_price,
313-
} => cmd_edit_order(&order_id, size.as_deref(), price.as_deref(), stop_price.as_deref())?,
313+
} => cmd_edit_order(
314+
&order_id,
315+
size.as_deref(),
316+
price.as_deref(),
317+
stop_price.as_deref(),
318+
)?,
314319

315320
FuturesPaperCommand::Cancel {
316321
order_id,
@@ -486,8 +491,8 @@ async fn cmd_place_order(
486491
.parse()
487492
.map_err(|_| BybitError::Paper(format!("Invalid size: {size_str}")))?;
488493

489-
let order_type = FuturesOrderType::from_str(order_type_str)
490-
.map_err(|e| BybitError::Paper(e))?;
494+
let order_type =
495+
FuturesOrderType::from_str(order_type_str).map_err(|e| BybitError::Paper(e))?;
491496

492497
let price = price_str
493498
.map(|s| s.parse::<f64>())
@@ -497,7 +502,12 @@ async fn cmd_place_order(
497502
let stop_price = stop_price_str
498503
.map(|s| s.parse::<f64>())
499504
.transpose()
500-
.map_err(|_| BybitError::Paper(format!("Invalid stop_price: {}", stop_price_str.unwrap_or(""))))?;
505+
.map_err(|_| {
506+
BybitError::Paper(format!(
507+
"Invalid stop_price: {}",
508+
stop_price_str.unwrap_or("")
509+
))
510+
})?;
501511

502512
let trigger_signal = trigger_signal_str
503513
.map(|s| TriggerSignal::from_str(s))
@@ -507,7 +517,9 @@ async fn cmd_place_order(
507517
let leverage = leverage_str
508518
.map(|s| s.parse::<f64>())
509519
.transpose()
510-
.map_err(|_| BybitError::Paper(format!("Invalid leverage: {}", leverage_str.unwrap_or(""))))?;
520+
.map_err(|_| {
521+
BybitError::Paper(format!("Invalid leverage: {}", leverage_str.unwrap_or("")))
522+
})?;
511523

512524
let trailing_max_dev = trailing_max_dev_str
513525
.map(|s| s.parse::<f64>())
@@ -613,7 +625,12 @@ fn cmd_edit_order(
613625
let stop_price = stop_price_str
614626
.map(|s| s.parse::<f64>())
615627
.transpose()
616-
.map_err(|_| BybitError::Paper(format!("Invalid stop_price: {}", stop_price_str.unwrap_or(""))))?;
628+
.map_err(|_| {
629+
BybitError::Paper(format!(
630+
"Invalid stop_price: {}",
631+
stop_price_str.unwrap_or("")
632+
))
633+
})?;
617634

618635
let _lock = futures_paper::StateLock::acquire()?;
619636
let mut state = futures_paper::load_state()?;
@@ -733,9 +750,7 @@ async fn cmd_batch_order(client: &BybitClient, orders_json: &str) -> BybitResult
733750
let state_category = futures_paper::load_state()?.category.clone();
734751
let mut snapshots: HashMap<String, MarketSnapshot> = HashMap::new();
735752
for sym in &symbols {
736-
if let Ok(snap) =
737-
futures_paper::fetch_market_snapshot(client, &state_category, sym).await
738-
{
753+
if let Ok(snap) = futures_paper::fetch_market_snapshot(client, &state_category, sym).await {
739754
snapshots.insert(sym.clone(), snap);
740755
}
741756
}

src/futures_paper.rs

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,8 @@ pub fn load_state() -> BybitResult<FuturesPaperState> {
362362
));
363363
}
364364
let contents = fs::read_to_string(&path)?;
365-
let state: FuturesPaperState = serde_json::from_str(&contents).map_err(|e| {
366-
BybitError::Parse(format!("Failed to parse futures paper state: {e}"))
367-
})?;
365+
let state: FuturesPaperState = serde_json::from_str(&contents)
366+
.map_err(|e| BybitError::Parse(format!("Failed to parse futures paper state: {e}")))?;
368367
Ok(state)
369368
}
370369

@@ -469,11 +468,7 @@ impl FuturesPaperState {
469468
(self.collateral + self.unrealized_pnl(mark_prices) - self.used_margin()).max(0.0)
470469
}
471470

472-
pub fn resolve_leverage(
473-
&self,
474-
order_leverage: Option<f64>,
475-
symbol: &str,
476-
) -> BybitResult<f64> {
471+
pub fn resolve_leverage(&self, order_leverage: Option<f64>, symbol: &str) -> BybitResult<f64> {
477472
let lev = order_leverage
478473
.or_else(|| self.leverage_preferences.get(symbol).copied())
479474
.unwrap_or(DEFAULT_LEVERAGE);
@@ -575,9 +570,9 @@ impl FuturesPaperState {
575570
market: &MarketSnapshot,
576571
mark_prices: &HashMap<String, f64>,
577572
) -> BybitResult<OrderPlacementResult> {
578-
let price = params.price.ok_or_else(|| {
579-
BybitError::Paper("Limit orders require --price".to_string())
580-
})?;
573+
let price = params
574+
.price
575+
.ok_or_else(|| BybitError::Paper("Limit orders require --price".to_string()))?;
581576
validate_finite_positive(price, "price")?;
582577

583578
// Check if immediately fillable
@@ -682,9 +677,9 @@ impl FuturesPaperState {
682677
leverage: f64,
683678
market: &MarketSnapshot,
684679
) -> BybitResult<OrderPlacementResult> {
685-
let price = params.price.ok_or_else(|| {
686-
BybitError::Paper("Post orders require --price".to_string())
687-
})?;
680+
let price = params
681+
.price
682+
.ok_or_else(|| BybitError::Paper("Post orders require --price".to_string()))?;
688683
validate_finite_positive(price, "price")?;
689684

690685
// Post-only: cancel if would immediately cross
@@ -699,13 +694,16 @@ impl FuturesPaperState {
699694
order_id,
700695
status: OrderStatus::Cancelled,
701696
fills: vec![],
702-
message: Some("Post-only order would cross the spread and was cancelled.".to_string()),
697+
message: Some(
698+
"Post-only order would cross the spread and was cancelled.".to_string(),
699+
),
703700
});
704701
}
705702

706703
let reserved_margin = params.size * price / leverage;
707-
let mark_prices: HashMap<String, f64> =
708-
[(params.symbol.to_uppercase(), market.mark)].into_iter().collect();
704+
let mark_prices: HashMap<String, f64> = [(params.symbol.to_uppercase(), market.mark)]
705+
.into_iter()
706+
.collect();
709707
let available = self.available_margin(&mark_prices);
710708
if !params.reduce_only && available < reserved_margin {
711709
return Err(BybitError::Paper(format!(
@@ -753,9 +751,9 @@ impl FuturesPaperState {
753751
leverage: f64,
754752
market: &MarketSnapshot,
755753
) -> BybitResult<OrderPlacementResult> {
756-
let price = params.price.ok_or_else(|| {
757-
BybitError::Paper("IOC orders require --price".to_string())
758-
})?;
754+
let price = params
755+
.price
756+
.ok_or_else(|| BybitError::Paper("IOC orders require --price".to_string()))?;
759757
validate_finite_positive(price, "price")?;
760758

761759
let fillable = match params.side {
@@ -769,7 +767,9 @@ impl FuturesPaperState {
769767
order_id,
770768
status: OrderStatus::Cancelled,
771769
fills: vec![],
772-
message: Some("IOC order could not fill immediately and was cancelled.".to_string()),
770+
message: Some(
771+
"IOC order could not fill immediately and was cancelled.".to_string(),
772+
),
773773
});
774774
}
775775

@@ -778,8 +778,9 @@ impl FuturesPaperState {
778778
Side::Short => market.bid.max(price),
779779
};
780780

781-
let mark_prices: HashMap<String, f64> =
782-
[(params.symbol.to_uppercase(), market.mark)].into_iter().collect();
781+
let mark_prices: HashMap<String, f64> = [(params.symbol.to_uppercase(), market.mark)]
782+
.into_iter()
783+
.collect();
783784
let available = self.available_margin(&mark_prices);
784785
let required_margin = params.size * fill_price / leverage;
785786
if !params.reduce_only && available < required_margin {
@@ -820,9 +821,9 @@ impl FuturesPaperState {
820821
leverage: f64,
821822
market: &MarketSnapshot,
822823
) -> BybitResult<OrderPlacementResult> {
823-
let price = params.price.ok_or_else(|| {
824-
BybitError::Paper("FOK orders require --price".to_string())
825-
})?;
824+
let price = params
825+
.price
826+
.ok_or_else(|| BybitError::Paper("FOK orders require --price".to_string()))?;
826827
validate_finite_positive(price, "price")?;
827828

828829
let fillable = match params.side {
@@ -836,7 +837,9 @@ impl FuturesPaperState {
836837
order_id,
837838
status: OrderStatus::Cancelled,
838839
fills: vec![],
839-
message: Some("FOK order could not fill in full immediately and was cancelled.".to_string()),
840+
message: Some(
841+
"FOK order could not fill in full immediately and was cancelled.".to_string(),
842+
),
840843
});
841844
}
842845

@@ -869,8 +872,9 @@ impl FuturesPaperState {
869872
Side::Short => market.bid.max(price),
870873
};
871874

872-
let mark_prices: HashMap<String, f64> =
873-
[(params.symbol.to_uppercase(), market.mark)].into_iter().collect();
875+
let mark_prices: HashMap<String, f64> = [(params.symbol.to_uppercase(), market.mark)]
876+
.into_iter()
877+
.collect();
874878
let available = self.available_margin(&mark_prices);
875879
let required_margin = params.size * fill_price / leverage;
876880
if !params.reduce_only && available < required_margin {
@@ -912,10 +916,7 @@ impl FuturesPaperState {
912916
mark_prices: &HashMap<String, f64>,
913917
) -> BybitResult<OrderPlacementResult> {
914918
let stop_price = params.stop_price.ok_or_else(|| {
915-
BybitError::Paper(format!(
916-
"{} orders require --stop-price",
917-
params.order_type
918-
))
919+
BybitError::Paper(format!("{} orders require --stop-price", params.order_type))
919920
})?;
920921
validate_finite_positive(stop_price, "stop_price")?;
921922

@@ -933,7 +934,8 @@ impl FuturesPaperState {
933934
.unwrap_or("percent");
934935
if unit != "percent" && unit != "quote_currency" {
935936
return Err(BybitError::Paper(
936-
"trailing_stop_deviation_unit must be 'percent' or 'quote_currency'".to_string(),
937+
"trailing_stop_deviation_unit must be 'percent' or 'quote_currency'"
938+
.to_string(),
937939
));
938940
}
939941
}
@@ -1080,8 +1082,7 @@ impl FuturesPaperState {
10801082
.iter()
10811083
.position(|o| {
10821084
order_id.is_some_and(|id| o.id == id)
1083-
|| client_order_id
1084-
.is_some_and(|cid| o.client_order_id.as_deref() == Some(cid))
1085+
|| client_order_id.is_some_and(|cid| o.client_order_id.as_deref() == Some(cid))
10851086
})
10861087
.ok_or_else(|| {
10871088
BybitError::Paper(
@@ -1203,9 +1204,7 @@ impl FuturesPaperState {
12031204
event_type: "realized_pnl".to_string(),
12041205
symbol: Some(symbol.to_string()),
12051206
amount: pnl,
1206-
details: format!(
1207-
"Closed {side} position: {size} @ {price:.4}, PnL = {pnl:.4}"
1208-
),
1207+
details: format!("Closed {side} position: {size} @ {price:.4}, PnL = {pnl:.4}"),
12091208
timestamp: now_rfc3339(),
12101209
};
12111210
self.history.push(event);
@@ -1299,12 +1298,7 @@ impl FuturesPaperState {
12991298
});
13001299
}
13011300

1302-
fn validate_reduce_only(
1303-
&self,
1304-
symbol: &str,
1305-
side: Side,
1306-
size: f64,
1307-
) -> BybitResult<()> {
1301+
fn validate_reduce_only(&self, symbol: &str, side: Side, size: f64) -> BybitResult<()> {
13081302
let pos = self
13091303
.positions
13101304
.iter()
@@ -1339,17 +1333,8 @@ impl FuturesPaperState {
13391333
let mut result = ReconcileResult::default();
13401334

13411335
self.reconcile_limit_orders(last_prices, mark_prices, &mut result.fills);
1342-
self.reconcile_triggered_orders(
1343-
mark_prices,
1344-
last_prices,
1345-
index_prices,
1346-
&mut result.fills,
1347-
);
1348-
self.reconcile_liquidations(
1349-
mark_prices,
1350-
maintenance_rates,
1351-
&mut result.liquidations,
1352-
);
1336+
self.reconcile_triggered_orders(mark_prices, last_prices, index_prices, &mut result.fills);
1337+
self.reconcile_liquidations(mark_prices, maintenance_rates, &mut result.liquidations);
13531338
self.reconcile_funding(funding_rates, mark_prices, &mut result.funding_events);
13541339

13551340
self.last_reconciled_at = Some(now_rfc3339());
@@ -1711,10 +1696,7 @@ pub fn compute_unrealized_pnl(pos: &FuturesPaperPosition, mark_price: f64) -> f6
17111696
compute_realized_pnl(pos.side, pos.entry_price, mark_price, pos.size)
17121697
}
17131698

1714-
pub fn compute_liquidation_price(
1715-
pos: &FuturesPaperPosition,
1716-
maintenance_margin_rate: f64,
1717-
) -> f64 {
1699+
pub fn compute_liquidation_price(pos: &FuturesPaperPosition, maintenance_margin_rate: f64) -> f64 {
17181700
if pos.entry_price <= 0.0 || pos.leverage <= 0.0 {
17191701
return f64::INFINITY;
17201702
}
@@ -1835,9 +1817,7 @@ pub async fn fetch_market_snapshot(
18351817
.as_array()
18361818
.and_then(|a| a.first())
18371819
.cloned()
1838-
.ok_or_else(|| {
1839-
BybitError::Paper(format!("No ticker data for symbol {symbol_upper}"))
1840-
})?;
1820+
.ok_or_else(|| BybitError::Paper(format!("No ticker data for symbol {symbol_upper}")))?;
18411821

18421822
let parse_f = |v: &Value| -> f64 {
18431823
v.as_str()

src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ pub mod client;
33
pub mod commands;
44
pub mod config;
55
pub mod errors;
6+
pub mod futures_paper;
67
pub mod mcp;
78
pub mod output;
8-
pub mod futures_paper;
99
pub mod paper;
1010
pub mod shell;
1111
pub mod telemetry;
@@ -196,7 +196,11 @@ pub enum Command {
196196
/// Start MCP server for AI tool use
197197
Mcp {
198198
/// Comma-separated service groups to expose, or "all"
199-
#[arg(short = 's', long, default_value = "market,account,paper,futures-paper")]
199+
#[arg(
200+
short = 's',
201+
long,
202+
default_value = "market,account,paper,futures-paper"
203+
)]
200204
services: String,
201205
/// Skip per-call confirmation for dangerous tools
202206
#[arg(long)]

src/mcp/registry.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3532,8 +3532,16 @@ pub fn tool_to_args(name: &str, p: &Value) -> Option<Vec<String>> {
35323532
opt!(args, "--trigger-signal", gs("trigger_signal"));
35333533
opt!(args, "--client-order-id", gs("client_order_id"));
35343534
opt!(args, "--leverage", gs("leverage"));
3535-
opt!(args, "--trailing-stop-max-deviation", gs("trailing_stop_max_deviation"));
3536-
opt!(args, "--trailing-stop-deviation-unit", gs("trailing_stop_deviation_unit"));
3535+
opt!(
3536+
args,
3537+
"--trailing-stop-max-deviation",
3538+
gs("trailing_stop_max_deviation")
3539+
);
3540+
opt!(
3541+
args,
3542+
"--trailing-stop-deviation-unit",
3543+
gs("trailing_stop_deviation_unit")
3544+
);
35373545
opt!(args, "--category", gs("category"));
35383546
if gb("reduce_only") {
35393547
args.push("--reduce-only".to_string());
@@ -3553,8 +3561,16 @@ pub fn tool_to_args(name: &str, p: &Value) -> Option<Vec<String>> {
35533561
opt!(args, "--trigger-signal", gs("trigger_signal"));
35543562
opt!(args, "--client-order-id", gs("client_order_id"));
35553563
opt!(args, "--leverage", gs("leverage"));
3556-
opt!(args, "--trailing-stop-max-deviation", gs("trailing_stop_max_deviation"));
3557-
opt!(args, "--trailing-stop-deviation-unit", gs("trailing_stop_deviation_unit"));
3564+
opt!(
3565+
args,
3566+
"--trailing-stop-max-deviation",
3567+
gs("trailing_stop_max_deviation")
3568+
);
3569+
opt!(
3570+
args,
3571+
"--trailing-stop-deviation-unit",
3572+
gs("trailing_stop_deviation_unit")
3573+
);
35583574
opt!(args, "--category", gs("category"));
35593575
if gb("reduce_only") {
35603576
args.push("--reduce-only".to_string());

0 commit comments

Comments
 (0)