Save and improved sell all
This commit is contained in:
Generated
+111
@@ -22,6 +22,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "1.0.0"
|
||||
@@ -262,6 +271,20 @@ dependencies = [
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.58"
|
||||
@@ -337,6 +360,27 @@ dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938"
|
||||
dependencies = [
|
||||
"csv-core",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv-core"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.11.1"
|
||||
@@ -726,6 +770,30 @@ dependencies = [
|
||||
"windows-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "2.2.0"
|
||||
@@ -1578,6 +1646,12 @@ version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
@@ -1735,6 +1809,8 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"csv",
|
||||
"env_logger",
|
||||
"futures-util",
|
||||
"log",
|
||||
@@ -2270,6 +2346,41 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
|
||||
@@ -17,3 +17,5 @@ env_logger = "0.11.11"
|
||||
rust_decimal = { version = "1.42.1", features = ["macros"] }
|
||||
reqwest = { version = "0.13.4", features = ["json"] }
|
||||
async-trait = "0.1.91"
|
||||
csv = "1.4.0"
|
||||
chrono = { version = "0.4.45", features = ["serde"] }
|
||||
|
||||
+2
-16
@@ -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(())
|
||||
|
||||
+36
-8
@@ -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.");
|
||||
match line.to_lowercase().trim() {
|
||||
"exit" | "shutdown" => {
|
||||
let _ = tx.send(true);
|
||||
break;
|
||||
}
|
||||
|
||||
"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
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user