Save and improved sell all

This commit is contained in:
2026-08-07 05:47:52 +02:00
parent 02cd4c6347
commit e6db04f612
5 changed files with 161 additions and 34 deletions
+2 -16
View File
@@ -121,24 +121,10 @@ impl ExecutorWrapper {
}
pub async fn sell_all(&mut self, priority: Decimal, slippage: u16) -> anyhow::Result<()> {
let positions: Vec<(String, Decimal)> = self
.positions
.iter()
.map(|(mint, amount)| (mint.clone(), *amount))
.collect();
for (mint, amount) in positions {
for (mint, _) in self.positions.drain() {
self.executor
.sell(&mint, amount, priority, slippage)
.sell_percent(&mint, 100, priority, slippage)
.await?;
if let Some(position) = self.positions.get_mut(&mint) {
*position -= amount;
if *position <= Decimal::ZERO {
self.positions.remove(&mint);
}
}
}
Ok(())
+37 -9
View File
@@ -5,22 +5,50 @@ pub mod strategy;
pub mod tradelog;
pub mod types;
use tokio::io::{self, AsyncBufReadExt, BufReader};
use tokio::sync::watch;
use std::sync::Arc;
use chrono::Local;
use tokio::{
io::{self, AsyncBufReadExt, BufReader},
sync::watch,
};
use crate::bot::Bot;
async fn shutdown_listener(tx: watch::Sender<bool>) {
async fn shutdown_listener(bot: Arc<Bot>, tx: watch::Sender<bool>) -> anyhow::Result<()> {
let stdin = BufReader::new(io::stdin());
let mut lines = stdin.lines();
while let Ok(Some(line)) = lines.next_line().await {
if line.trim().eq_ignore_ascii_case("exit") {
println!("Shutdown requested.");
let _ = tx.send(true);
break;
match line.to_lowercase().trim() {
"exit" | "shutdown" => {
let _ = tx.send(true);
}
"save" => {
log::info!("Saving trades");
let now = Local::now();
let formatted_time = now.format("%m-%d-%H-%M").to_string();
let filename = format!("sol-hun-{}.csv", formatted_time);
let mut writer = csv::Writer::from_path(&filename)?;
for trade in bot.trade_log.lock().await.iter() {
writer.serialize(trade)?;
}
writer.flush()?;
log::info!("Saved trades to {}", filename);
}
_ => {}
}
}
Ok(())
}
#[tokio::main]
@@ -31,9 +59,9 @@ async fn main() -> anyhow::Result<()> {
let (shutdown_tx, shutdown_rx) = watch::channel(false);
tokio::spawn(shutdown_listener(shutdown_tx));
let bot = Bot::new().await?;
tokio::spawn(shutdown_listener(bot.clone(), shutdown_tx));
bot.start(shutdown_rx).await
}
+9 -9
View File
@@ -1,6 +1,6 @@
use std::time::{Duration, Instant};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ExitReason {
TakeProfit,
StopLoss,
@@ -8,18 +8,18 @@ pub enum ExitReason {
MomentumStalled,
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TradeLog {
pub mint: String,
pub opened_at: Instant,
pub closed_at: Option<Instant>,
pub opened_at: chrono::DateTime<chrono::Utc>,
pub closed_at: Option<chrono::DateTime<chrono::Utc>>,
pub entry_price_sol: f64,
pub exit_price_sol: Option<f64>,
pub pnl_percent: Option<f64>,
pub duration: Option<Duration>,
pub duration: Option<chrono::TimeDelta>,
pub exit_reason: Option<ExitReason>,
@@ -39,7 +39,7 @@ impl TradeLog {
) -> Self {
Self {
mint,
opened_at: Instant::now(),
opened_at: chrono::Utc::now(),
closed_at: None,
entry_price_sol,
@@ -57,7 +57,7 @@ impl TradeLog {
}
pub fn close(&mut self, exit_price_sol: f64, reason: ExitReason) {
let now = Instant::now();
let now = chrono::Utc::now();
let pnl = ((exit_price_sol - self.entry_price_sol) / self.entry_price_sol) * 100.0;
@@ -65,7 +65,7 @@ impl TradeLog {
self.pnl_percent = Some(pnl);
self.closed_at = Some(now);
self.duration = Some(now.duration_since(self.opened_at));
self.duration = Some(now.signed_duration_since(self.opened_at));
self.exit_reason = Some(reason);
}