copy_trading/position/
process_market_update.rs

1use crate::types::position::Position;
2use crate::types::position_close_reason::PositionCloseReason;
3use crate::types::position_manager::PositionManager;
4use crate::types::position_status::PositionStatus;
5use solana_central::constants::LAMPORTS_PER_SOL;
6use solana_central::MarketUpdate;
7use std::sync::{Arc, Mutex};
8
9impl Position {
10  /// Process a market update for an open position, checking stop-loss conditions. Implements
11  /// trailing stop-loss by adjusting the stop-loss price upward as price increases. Closes the
12  /// position if current price falls below the lowest acceptable price threshold.
13  pub fn process_market_update(
14    position: &mut Position,
15    market_update: &MarketUpdate,
16    position_arc: &Arc<Mutex<Position>>,
17    position_manager: &Arc<PositionManager>,
18  ) {
19    let should_close_position;
20
21    // Only process if position is open
22    if position.status != PositionStatus::Open {
23      return;
24    }
25
26    // Only process if stop loss is enabled
27    if !position.config.use_stop_loss {
28      return;
29    }
30
31    let current_price = if position.sol_token_a {
32      market_update.price_a_b
33    } else {
34      market_update.price_b_a
35    };
36
37    // Move base price up if trailing stop loss is enabled and current price is greater than the base price
38    if position.config.trailing_stop_loss && current_price > position.stop_loss_price_lp {
39      position.stop_loss_price_lp = current_price;
40      position.lowest_acceptable_price_lp = current_price
41        * (LAMPORTS_PER_SOL - position.config.stop_loss_threshold_lp as u128)
42        / LAMPORTS_PER_SOL;
43      should_close_position = false;
44    }
45    // Do the main check for stop loss
46    else if current_price <= position.lowest_acceptable_price_lp {
47      should_close_position = true;
48    } else {
49      should_close_position = false;
50    }
51    let token_address = position.token_address.to_string();
52
53    // Close position outside of the mutex lock to avoid deadlock
54    if should_close_position {
55      println!(
56        "POSITION: Stop loss triggered for token: {}. Closing position.",
57        token_address
58      );
59
60      let p = position_arc.clone();
61      let pm = position_manager.clone();
62      tokio::spawn(async move {
63        Position::close_position(p, PositionCloseReason::StopLoss, pm);
64      });
65    }
66  }
67}