diff --git a/rustybot/Cargo.lock b/rustybot/Cargo.lock index 0b385b8..5025cfb 100644 --- a/rustybot/Cargo.lock +++ b/rustybot/Cargo.lock @@ -35,6 +35,17 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.9", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -198,6 +209,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "colored" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" +dependencies = [ + "atty", + "lazy_static", + "winapi 0.3.9", +] + [[package]] name = "core-foundation" version = "0.9.1" @@ -269,6 +291,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fern" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9a4820f0ccc8a7afd67c39a0f1a0f4b07ca1725164271a64939d7aeb9af065" +dependencies = [ + "colored", + "log 0.4.11", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1097,7 +1129,9 @@ dependencies = [ "async-trait", "bitfinex", "dyn-clone", + "fern", "futures-util", + "log 0.4.11", "regex", "tokio 0.2.24", "tokio-tungstenite", diff --git a/rustybot/Cargo.toml b/rustybot/Cargo.toml index 3985630..e328703 100644 --- a/rustybot/Cargo.toml +++ b/rustybot/Cargo.toml @@ -13,4 +13,6 @@ tokio-tungstenite = "*" futures-util = { version = "0.3", default-features = false, features = ["async-await", "sink", "std"] } async-trait = "0.1" regex = "1" -dyn-clone = "1" \ No newline at end of file +dyn-clone = "1" +log = "0.4" +fern = {version = "0.6", features = ["colored"]} \ No newline at end of file diff --git a/rustybot/src/bot.rs b/rustybot/src/bot.rs index f023d97..bea705a 100644 --- a/rustybot/src/bot.rs +++ b/rustybot/src/bot.rs @@ -1,18 +1,12 @@ use core::time::Duration; -use std::collections::HashMap; -use bitfinex::api::Bitfinex; -use bitfinex::positions::Position; -use bitfinex::ticker::TradingPairTicker; -use futures_util::stream::FuturesUnordered; -use tokio::stream::StreamExt; +use log::{error, info}; use tokio::time::delay_for; -use crate::connectors::{Client, Connector, ExchangeKind}; +use crate::connectors::{Client, ExchangeKind}; use crate::currency::{Symbol, SymbolPair}; -use crate::events::{Event, EventKind}; +use crate::events::Event; use crate::managers::{OrderManager, PositionManager, PriceManager}; -use crate::strategy::PositionStrategy; use crate::ticker::Ticker; use crate::BoxError; @@ -61,10 +55,16 @@ impl BfxBot { } pub async fn start_loop(&mut self) -> Result<(), BoxError> { - self.update_managers().await?; + if let Err(e) = self.update_managers().await { + error!("Error while starting managers: {}", e); + } loop { - self.update().await; + info!("Current tick: {}", self.ticker.current_tick()); + + if let Err(e) = self.update().await { + error!("Error in main bot loop: {}", e); + } } } @@ -72,7 +72,9 @@ impl BfxBot { delay_for(self.ticker.duration()).await; self.ticker.inc(); - self.update_managers().await?; + if let Err(e) = self.update_managers().await { + error!("Error while updating managers: {}", e); + } Ok(()) } @@ -89,8 +91,6 @@ impl BfxBot { let tick = self.ticker.current_tick(); mgr.update(tick).await?; - - println!("{:?}", mgr); } Ok(None) @@ -117,7 +117,7 @@ impl BfxBot { price_entries.push(f.await??); } - for mut manager in &mut self.price_managers { + for manager in &mut self.price_managers { let prices: Vec<_> = price_entries .drain_filter(|x| x.pair() == manager.pair()) .collect(); diff --git a/rustybot/src/connectors.rs b/rustybot/src/connectors.rs index c7c99df..8f9dd49 100644 --- a/rustybot/src/connectors.rs +++ b/rustybot/src/connectors.rs @@ -1,4 +1,5 @@ -use std::convert::{TryFrom, TryInto}; +use std::convert::TryInto; +use std::fmt::{Debug, Formatter}; use std::sync::Arc; use async_trait::async_trait; @@ -6,10 +7,9 @@ use bitfinex::api::Bitfinex; use bitfinex::orders::{OrderForm, OrderMeta}; use bitfinex::ticker::TradingPairTicker; -use crate::currency::{Symbol, SymbolPair}; +use crate::currency::SymbolPair; use crate::models::{Order, OrderKind, Position, PositionState, PriceTicker}; use crate::BoxError; -use std::fmt::{Debug, Formatter}; #[derive(Eq, PartialEq, Hash, Clone, Debug)] pub enum ExchangeKind { diff --git a/rustybot/src/currency.rs b/rustybot/src/currency.rs index b5b0fd3..87f02be 100644 --- a/rustybot/src/currency.rs +++ b/rustybot/src/currency.rs @@ -1,7 +1,7 @@ use core::fmt; use std::borrow::Cow; use std::convert::TryFrom; -use std::fmt::{Display, Error, Formatter}; +use std::fmt::{Display, Formatter}; use regex::Regex; diff --git a/rustybot/src/events.rs b/rustybot/src/events.rs index 6bff8cc..6229c3f 100644 --- a/rustybot/src/events.rs +++ b/rustybot/src/events.rs @@ -1,13 +1,10 @@ -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::future::Future; -use tokio::stream::StreamExt; use tokio::task::JoinHandle; -use crate::bot::BfxBot; use crate::managers::PriceManager; use crate::models::{Position, PositionProfitState}; -use crate::BoxError; #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum SignalKind { diff --git a/rustybot/src/main.rs b/rustybot/src/main.rs index de05953..41f24cd 100644 --- a/rustybot/src/main.rs +++ b/rustybot/src/main.rs @@ -1,13 +1,12 @@ #![feature(drain_filter)] -use std::thread::JoinHandle; - -use tokio::time::{delay_for, Duration}; +use fern::colors::{Color, ColoredLevelConfig}; +use log::LevelFilter::Info; +use tokio::time::Duration; use crate::bot::BfxBot; -use crate::connectors::{BitfinexConnector, ExchangeKind}; -use crate::currency::{Symbol, SymbolPair}; -use crate::events::SignalKind; +use crate::connectors::ExchangeKind; +use crate::currency::Symbol; mod bot; mod connectors; @@ -22,6 +21,8 @@ pub type BoxError = Box; #[tokio::main] async fn main() -> Result<(), BoxError> { + setup_logger()?; + let test_api_key = "P1EVE68DJByDAkGQvpIkTwfrbYXd2Vo2ZaIhTYb9vx2"; let test_api_secret = "1nicg8z0zKVEt5Rb7ZDpIYjVYVTgvCaCPMZqB0niFli"; let affiliate_code = "XPebOgHxA"; @@ -41,3 +42,29 @@ async fn main() -> Result<(), BoxError> { Ok(bot.start_loop().await?) } + +fn setup_logger() -> Result<(), fern::InitError> { + let colors = ColoredLevelConfig::new() + .info(Color::Green) + .error(Color::Red) + .trace(Color::Blue) + .debug(Color::Cyan) + .warn(Color::Yellow); + + fern::Dispatch::new() + .format(move |out, message, record| { + out.finish(format_args!( + "[{}][{}] {}", + record.target(), + colors.color(record.level()), + message + )) + }) + .level(Info) + .filter(|metadata| metadata.target().contains("rustybot")) + .chain(std::io::stdout()) + .chain(fern::log_file("rustico.log")?) + .apply()?; + + Ok(()) +} diff --git a/rustybot/src/managers.rs b/rustybot/src/managers.rs index 4a0d0c9..9db42d6 100644 --- a/rustybot/src/managers.rs +++ b/rustybot/src/managers.rs @@ -1,11 +1,10 @@ -use std::collections::{HashMap, VecDeque}; +use std::collections::HashMap; -use crate::connectors::{Client, Connector}; +use crate::connectors::Client; use crate::currency::SymbolPair; -use crate::events::{Event, EventDispatcher, SignalKind}; +use crate::events::{Event, SignalKind}; use crate::models::{Order, Position, PriceTicker}; use crate::strategy::PositionStrategy; -use crate::ticker::Ticker; use crate::BoxError; pub struct EventManager { @@ -173,7 +172,7 @@ impl PositionManager { } pub async fn update(&mut self, tick: u64) -> Result>, BoxError> { - let mut opt_active_positions = self.client.active_positions(&self.pair).await?; + let opt_active_positions = self.client.active_positions(&self.pair).await?; let mut events = vec![]; if opt_active_positions.is_none() { diff --git a/rustybot/src/strategy.rs b/rustybot/src/strategy.rs index 11f569c..a6fe086 100644 --- a/rustybot/src/strategy.rs +++ b/rustybot/src/strategy.rs @@ -1,11 +1,11 @@ -use std::collections::HashMap; - -use crate::events::{Event, EventKind, EventMetadata, SignalKind}; -use crate::managers::{PositionManager, PriceManager}; -use crate::models::{Position, PositionProfitState}; -use dyn_clone::DynClone; use std::fmt::{Debug, Formatter}; +use dyn_clone::DynClone; + +use crate::events::{Event, SignalKind}; +use crate::managers::PositionManager; +use crate::models::Position; + pub trait PositionStrategy: DynClone { fn on_new_tick( &self,