Practice
Update real time token metrix about bought token
/// Update metrics for a token based on parsed transaction data
pub async fn update_metrics(&self, token_mint: &str, parsed_data: &ParsedData) -> Result<()> {
let logger = Logger::new("[SELLING-STRATEGY] => ".magenta().to_string());
// Extract data
let sol_change = parsed_data.sol_change;
let token_change = parsed_data.token_change;
let is_buy = parsed_data.is_buy;
let timestamp = parsed_data.timestamp.unwrap_or_else(|| {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
});
// Get wallet pubkey
let wallet_pubkey = self.app_state.wallet.try_pubkey()
.map_err(|e| anyhow!("Failed to get wallet pubkey: {}", e))?;
// Get token account to determine actual balance
let token_pubkey = Pubkey::from_str(token_mint)
.map_err(|e| anyhow!("Invalid token mint address: {}", e))?;
let ata = get_associated_token_address(&wallet_pubkey, &token_pubkey);
// Get current token balance
let actual_token_balance = match self.app_state.rpc_nonblocking_client.get_token_account(&ata).await {
Ok(Some(account)) => {
let amount_value = account.token_amount.amount.parse::<f64>()
.map_err(|e| anyhow!("Failed to parse token amount: {}", e))?;
amount_value / 10f64.powi(account.token_amount.decimals as i32)
},
Ok(None) => 0.0,
Err(_) => 0.0,
};
// Calculate price if possible
let price = if token_change != 0.0 && sol_change != 0.0 {
(sol_change / token_change).abs()
} else {
0.0
};
if price <= 0.0 {
logger.log(format!("Invalid price calculated: {}", price));
return Err(anyhow!("Invalid price calculation"));
}
// Update token metrics using entry API
let mut entry = TOKEN_METRICS.entry(token_mint.to_string()).or_insert_with(|| TokenMetrics {
entry_price: 0.0,
highest_price: 0.0,
lowest_price: 0.0,
current_price: 0.0,
volume_24h: 0.0,
market_cap: 0.0,
time_held: 0,
last_update: Instant::now(),
buy_timestamp: timestamp,
amount_held: 0.0,
cost_basis: 0.0,
price_history: VecDeque::new(),
volume_history: VecDeque::new(),
liquidity_at_entry: 0.0,
});
// Update metrics based on transaction type
if is_buy {
// For buys, update entry price using weighted average
let token_amount = token_change.abs();
let sol_amount = sol_change.abs();
if token_amount > 0.0 {
// Calculate new weighted average entry price
let new_entry_price = if entry.amount_held > 0.0 {
// Weighted average of existing position and new purchase
((entry.entry_price * entry.amount_held) + (price * token_amount))
/ (entry.amount_held + token_amount)
} else {
// First purchase
price
};
// Update entry price and cost basis
entry.entry_price = new_entry_price;
entry.cost_basis += sol_amount;
logger.log(format!(
"Updated entry price for buy: old={}, new={} (weighted avg)",
entry.entry_price, new_entry_price
));
}
} else {
// For sells, adjust cost basis proportionally but keep entry price
if entry.amount_held > 0.0 && entry.cost_basis > 0.0 {
let sell_percentage = token_change.abs() / entry.amount_held;
entry.cost_basis *= 1.0 - sell_percentage;
logger.log(format!(
"Adjusted cost basis for sell: new={} (reduced by {}%)",
entry.cost_basis, sell_percentage * 100.0
));
}
}
// Always update amount held with actual balance
entry.amount_held = actual_token_balance;
// Always update current price
entry.current_price = price;
// Update highest price if applicable
if price > entry.highest_price {
entry.highest_price = price;
}
// Update lowest price if applicable (initialize or update if lower)
if entry.lowest_price == 0.0 || price < entry.lowest_price {
entry.lowest_price = price;
}
// Update price history
entry.price_history.push_back(price);
if entry.price_history.len() > 20 { // Keep last 20 prices
entry.price_history.pop_front();
}
// Log current metrics
let pnl = if entry.entry_price > 0.0 {
((price - entry.entry_price) / entry.entry_price) * 100.0
} else {
0.0
};
logger.log(format!(
"Token metrics for {}: Price: {}, Entry: {}, Highest: {}, Lowest: {}, PNL: {:.2}%, Balance: {}",
token_mint, price, entry.entry_price, entry.highest_price, entry.lowest_price, pnl, actual_token_balance
));
Ok(())
}
https://github.com/deniyuda348/pump-fun-pump-swap-sniper-copy-bot/wiki/diagram-about-selling
Top comments (0)