Skip to content

Commit d423fd4

Browse files
committed
index and peak value
1 parent b47b041 commit d423fd4

1 file changed

Lines changed: 98 additions & 76 deletions

File tree

  • crates/core/src/strategy

crates/core/src/strategy/mod.rs

Lines changed: 98 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{collections::HashMap, sync::Arc};
88

99
use color_eyre::eyre::{self, Context, eyre};
1010
use num_bigint::BigUint;
11+
use num_traits::Zero;
1112
use tracing::{debug, error, instrument, trace, warn};
1213
use tycho_common::models::token::Token;
1314
use tycho_simulation::{
@@ -345,45 +346,64 @@ impl CrossChainSingleHop {
345346
fast_height: u64,
346347
fast_inventory: &BigUint,
347348
) -> Option<signals::CrossChainSingleHop> {
349+
if slow_sims.is_empty() {
350+
trace!("no slow sims provided for binary search; cannot find optimal signal");
351+
return None;
352+
}
348353
let (mut left, mut right) = (0, slow_sims.len() - 1);
349354

350-
let mut best_signal: Option<signals::CrossChainSingleHop> = None;
351-
352355
while left < right {
353-
let mid = (right + left) / 2;
354-
355-
// make sims for mid
356-
let mid_signal = match self.try_signal_from_precompute(
357-
slow_sims[mid].clone(),
358-
slow_protocol_component.clone(),
359-
slow_pool_id,
360-
slow_height,
361-
slow_prices_a_b,
362-
slow_prices_a_usdc,
363-
slow_prices_b_usdc,
364-
fast_state,
365-
fast_protocol_component.clone(),
366-
fast_pool_id,
367-
fast_height,
368-
fast_inventory,
369-
) {
370-
Ok(signal) => signal,
371-
Err(err) => {
372-
trace!(index = mid, err = %err, "failed to make mid signal, searching over smaller values");
373-
right = mid - 1;
374-
continue;
375-
}
376-
};
356+
let mid = left + (right - left) / 2;
357+
let mid_profit_usdc = self
358+
.get_profit_and_signal(
359+
mid,
360+
slow_sims,
361+
slow_protocol_component.clone(),
362+
slow_pool_id,
363+
slow_height,
364+
slow_prices_a_b,
365+
slow_prices_a_usdc,
366+
slow_prices_b_usdc,
367+
fast_state,
368+
fast_protocol_component.clone(),
369+
fast_pool_id,
370+
fast_height,
371+
fast_inventory,
372+
)
373+
.map(|(_, p)| p)
374+
.unwrap_or_default();
375+
let next_profit_usdc = self
376+
.get_profit_and_signal(
377+
mid + 1,
378+
slow_sims,
379+
slow_protocol_component.clone(),
380+
slow_pool_id,
381+
slow_height,
382+
slow_prices_a_b,
383+
slow_prices_a_usdc,
384+
slow_prices_b_usdc,
385+
fast_state,
386+
fast_protocol_component.clone(),
387+
fast_pool_id,
388+
fast_height,
389+
fast_inventory,
390+
)
391+
.map(|(_, p)| p)
392+
.unwrap_or_default();
377393

378-
trace!(
379-
index = mid,
380-
expected_profit = %mid_signal.expected_profit,
381-
"Generated mid candidate signal"
382-
);
394+
if mid_profit_usdc < next_profit_usdc {
395+
// next is higher -> check to the right (try a higher amount_in)
396+
trace!(index = mid, left = %left, right = %right, mid_profit_usdc = %mid_profit_usdc, next_profit_usdc = %next_profit_usdc, "mid+1 signal has higher expected profit, continuing search");
397+
left = mid + 1;
398+
} else {
399+
right = mid;
400+
}
401+
}
383402

384-
// make sims for mid+1
385-
let next_signal = match self.try_signal_from_precompute(
386-
slow_sims[mid + 1].clone(),
403+
let (best_signal, profit) = self
404+
.get_profit_and_signal(
405+
left,
406+
slow_sims,
387407
slow_protocol_component.clone(),
388408
slow_pool_id,
389409
slow_height,
@@ -395,51 +415,16 @@ impl CrossChainSingleHop {
395415
fast_pool_id,
396416
fast_height,
397417
fast_inventory,
398-
) {
399-
Ok(signal) => signal,
400-
Err(err) => {
401-
trace!(index = mid+1, err = %err, "failed to make mid+1 signal, searching over smaller values");
402-
right = mid;
403-
continue;
404-
}
405-
};
406-
trace!(
407-
index = mid+1,
408-
expected_profit = %next_signal.expected_profit,
409-
"Generated mid+1 candidate signal"
410-
);
418+
)
419+
.map(|(sig, p)| (sig, p))?;
411420

412-
// compare the expected profits
413-
let mid_profit_usdc = match mid_signal.expected_profit.total_profit_usdc() {
414-
Ok(profit) => profit,
415-
Err(err) => {
416-
error!(index = mid+1, err = %err, profit = %mid_signal.expected_profit, "failed to calculate mid+1 signal profit");
417-
continue;
418-
}
419-
};
420-
let next_profit_usdc = match next_signal.expected_profit.total_profit_usdc() {
421-
Ok(profit) => profit,
422-
Err(err) => {
423-
error!(index = mid+1, err = %err, profit = %next_signal.expected_profit, "failed to calculate next signal profit");
424-
continue;
425-
}
426-
};
421+
trace!(index = %left, found_signal = %best_signal, "search complete");
427422

428-
if mid_profit_usdc < next_profit_usdc {
429-
// next is higher -> check to the right (try a higher amount_in)
430-
trace!(index = mid, left = %left, right = %right, "mid+1 signal has higher expected profit, continuing search");
431-
best_signal = Some(next_signal);
432-
left = mid + 1;
433-
} else {
434-
// next is lower -> check to the left (try a lower amount_in)
435-
trace!(index = mid, left = %left, right = %right, "mid+1 signal has lower expected profit, continuing search");
436-
right = mid;
437-
}
423+
if profit.is_zero() {
424+
trace!("best signal has zero profit, returning None");
425+
return None;
438426
}
439-
440-
trace!(index = %left, found_signal = %best_signal.is_some(), "search complete");
441-
442-
best_signal
427+
Some(best_signal)
443428
}
444429

445430
/// This creates the fast leg of the arbitrage out of the precompute slow leg.
@@ -525,6 +510,43 @@ impl CrossChainSingleHop {
525510
})
526511
}
527512

513+
// Helper to keep the main loop clean
514+
fn get_profit_and_signal(
515+
&self,
516+
index: usize,
517+
slow_sims: &[Swap],
518+
slow_protocol_component: Arc<ProtocolComponent>,
519+
slow_pool_id: &PoolId,
520+
slow_height: u64,
521+
slow_prices_a_b: &SpotPrices,
522+
slow_prices_a_usdc: &Option<SpotPrices>,
523+
slow_prices_b_usdc: &Option<SpotPrices>,
524+
fast_state: &dyn ProtocolSim,
525+
fast_protocol_component: Arc<ProtocolComponent>,
526+
fast_pool_id: &PoolId,
527+
fast_height: u64,
528+
fast_inventory: &BigUint,
529+
) -> Option<(signals::CrossChainSingleHop, BigUint)> {
530+
let sig = self
531+
.try_signal_from_precompute(
532+
slow_sims[index].clone(),
533+
slow_protocol_component,
534+
slow_pool_id,
535+
slow_height,
536+
slow_prices_a_b,
537+
slow_prices_a_usdc,
538+
slow_prices_b_usdc,
539+
fast_state,
540+
fast_protocol_component,
541+
fast_pool_id,
542+
fast_height,
543+
fast_inventory,
544+
)
545+
.ok()?;
546+
let profit = sig.expected_profit.total_profit_usdc().ok()?;
547+
Some((sig, profit))
548+
}
549+
528550
pub fn token_a_symbol(&self) -> &str {
529551
&self.slow_pair.token_a().symbol
530552
}

0 commit comments

Comments
 (0)