Removed risk
This commit is contained in:
+1
-31
@@ -6,7 +6,7 @@ pub use hypersdk;
|
|||||||
|
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
use crate::plugin::{RiskEngineMessage, StrategyEngineMessage};
|
use crate::plugin::StrategyEngineMessage;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::general::*;
|
pub use crate::general::*;
|
||||||
@@ -112,33 +112,3 @@ pub trait Strategy {
|
|||||||
unimplemented!("Strategy::candlestick")
|
unimplemented!("Strategy::candlestick")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(async_fn_in_trait)]
|
|
||||||
pub trait Risk {
|
|
||||||
engine_methods!(prelude::RiskMessage);
|
|
||||||
|
|
||||||
async fn on_raw(&self, data: &[u8]) -> tokio::io::Result<()> {
|
|
||||||
match map_postcard_err(postcard::from_bytes(&data))? {
|
|
||||||
RiskEngineMessage::Initialize => self.initialize().await,
|
|
||||||
RiskEngineMessage::Command { command, args } => self.command(command, args).await,
|
|
||||||
RiskEngineMessage::WatchList(watchlist) => self.watchlist(watchlist).await,
|
|
||||||
RiskEngineMessage::Signal(signal) => self.signal_request(signal).await,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn initialize(&self) -> tokio::io::Result<()> {
|
|
||||||
unimplemented!("Risk::initialize")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn command(&self, _command: String, _args: Vec<String>) -> tokio::io::Result<()> {
|
|
||||||
unimplemented!("Risk::command")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn watchlist(&self, _watchlist: Vec<prelude::MarketItem>) -> tokio::io::Result<()> {
|
|
||||||
unimplemented!("Risk::watchlist")
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn signal_request(&self, _signal: prelude::StrategySignal) -> tokio::io::Result<()> {
|
|
||||||
unimplemented!("Risk::signal_request")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-51
@@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
general::{EventLog, Signal},
|
general::{EventLog, Signal},
|
||||||
terminal::MarketItem,
|
terminal::MarketItem,
|
||||||
units::Direction,
|
|
||||||
};
|
};
|
||||||
use hypersdk::hypercore::{Candle, CandleInterval, Incoming, Subscription};
|
use hypersdk::hypercore::{Candle, CandleInterval, Incoming, Subscription};
|
||||||
|
|
||||||
@@ -13,17 +12,6 @@ pub struct StrategyManifest {
|
|||||||
pub version: String,
|
pub version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct RiskManifest {
|
|
||||||
pub name: String,
|
|
||||||
pub description: String,
|
|
||||||
pub author: String,
|
|
||||||
pub version: String,
|
|
||||||
|
|
||||||
pub max_loss: u8,
|
|
||||||
pub cooldown: CandleInterval,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum StrategyMessage {
|
pub enum StrategyMessage {
|
||||||
Log(EventLog),
|
Log(EventLog),
|
||||||
@@ -42,16 +30,7 @@ pub enum StrategyMessage {
|
|||||||
|
|
||||||
UnsubscribeAll,
|
UnsubscribeAll,
|
||||||
|
|
||||||
Signal(StrategySignal),
|
Signal(Signal),
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
||||||
pub enum RiskMessage {
|
|
||||||
Log(EventLog),
|
|
||||||
|
|
||||||
GetWatchList,
|
|
||||||
|
|
||||||
Signal(RiskSignal),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
@@ -73,32 +52,3 @@ pub enum StrategyEngineMessage {
|
|||||||
candles: Vec<Candle>,
|
candles: Vec<Candle>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
||||||
pub enum RiskEngineMessage {
|
|
||||||
Initialize,
|
|
||||||
|
|
||||||
WatchList(Vec<MarketItem>),
|
|
||||||
|
|
||||||
Command { command: String, args: Vec<String> },
|
|
||||||
|
|
||||||
Signal(StrategySignal),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct StrategySignal {
|
|
||||||
pub symbol: String,
|
|
||||||
pub side: Direction,
|
|
||||||
pub confidence: f32,
|
|
||||||
pub price: Option<f64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
||||||
pub enum RiskSignal {
|
|
||||||
Approve(Signal),
|
|
||||||
Reject {
|
|
||||||
signal: StrategySignal,
|
|
||||||
rejection_confidence: f32,
|
|
||||||
reason: String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
general::{EventLog, MarketTrend, Position},
|
general::{EventLog, MarketTrend, Position, Signal},
|
||||||
plugin::{RiskManifest, RiskSignal, StrategyManifest},
|
plugin::StrategyManifest,
|
||||||
units::{Symbol, USD, Volatility},
|
units::{Symbol, USD, Volatility},
|
||||||
};
|
};
|
||||||
use hypersdk::{Decimal, hypercore::CandleInterval};
|
use hypersdk::{Decimal, hypercore::CandleInterval};
|
||||||
|
|
||||||
pub type SignalStatus = Result<RiskSignal, RiskSignal>;
|
pub type SignalStatus = Result<Signal, Signal>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum TerminalServerMessage {
|
pub enum TerminalServerMessage {
|
||||||
@@ -110,7 +110,6 @@ pub enum ItemState {
|
|||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Strategy {
|
pub struct Strategy {
|
||||||
pub strategy: StrategyManifest,
|
pub strategy: StrategyManifest,
|
||||||
pub risk: RiskManifest,
|
|
||||||
|
|
||||||
pub mode: Mode,
|
pub mode: Mode,
|
||||||
pub state: ItemState,
|
pub state: ItemState,
|
||||||
|
|||||||
@@ -69,32 +69,6 @@ impl Engine {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"risk" | "rs" => {
|
|
||||||
set_cfg!(id, {
|
|
||||||
let id: String = id;
|
|
||||||
|
|
||||||
if !crate::store::pulse_plugin(&id)?
|
|
||||||
.join("risk.toml")
|
|
||||||
.exists()
|
|
||||||
{
|
|
||||||
return self
|
|
||||||
.terminal_server
|
|
||||||
.error(
|
|
||||||
"config::set::risk",
|
|
||||||
&format!("Non existent risk `{id}`"),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.strategy.reload_risk(id.as_str()).await?;
|
|
||||||
self.config.lock().await.risk = id;
|
|
||||||
});
|
|
||||||
|
|
||||||
self.terminal_server
|
|
||||||
.info("config::set", "risk set successfully, use `config save` to persist changes")
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
"cooldown" | "cool" | "cd" => {
|
"cooldown" | "cool" | "cd" => {
|
||||||
set_cfg!(cooldown, {
|
set_cfg!(cooldown, {
|
||||||
self.config.lock().await.cooldown = cooldown;
|
self.config.lock().await.cooldown = cooldown;
|
||||||
@@ -102,7 +76,7 @@ impl Engine {
|
|||||||
self.terminal_server.broadcast(
|
self.terminal_server.broadcast(
|
||||||
pulse_sdk::terminal::TerminalServerMessage::StrategyUpdated(Strategy {
|
pulse_sdk::terminal::TerminalServerMessage::StrategyUpdated(Strategy {
|
||||||
strategy: self.strategy.strategy.manifest.lock().await.clone(),
|
strategy: self.strategy.strategy.manifest.lock().await.clone(),
|
||||||
risk: self.strategy.risk.manifest.lock().await.clone(),
|
|
||||||
mode: Mode::Auto,
|
mode: Mode::Auto,
|
||||||
state: ItemState::Running,
|
state: ItemState::Running,
|
||||||
cooldown,
|
cooldown,
|
||||||
@@ -114,7 +88,7 @@ impl Engine {
|
|||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
self.terminal_server
|
self.terminal_server
|
||||||
.error("config::set", "Invalid usage, available options: watchlist, strategy, risk, cooldown")
|
.error("config::set", "Invalid usage, available options: watchlist, strategy, cooldown")
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ impl Engine {
|
|||||||
pub async fn new() -> tokio::io::Result<Arc<Self>> {
|
pub async fn new() -> tokio::io::Result<Arc<Self>> {
|
||||||
let config = Config::new().await?;
|
let config = Config::new().await?;
|
||||||
|
|
||||||
let strategy = StrategyEngine::new(&config.strategy, &config.risk).await?;
|
let strategy = StrategyEngine::new(&config.strategy).await?;
|
||||||
|
|
||||||
let accounts = Arc::new(Mutex::new(AccountList::new().await?));
|
let accounts = Arc::new(Mutex::new(AccountList::new().await?));
|
||||||
let config = Arc::new(Mutex::new(config));
|
let config = Arc::new(Mutex::new(config));
|
||||||
|
|||||||
+19
-92
@@ -20,7 +20,6 @@ use crate::{
|
|||||||
|
|
||||||
pub struct StrategyEngine {
|
pub struct StrategyEngine {
|
||||||
pub strategy: Arc<Plugin<StrategyEngineMessage, StrategyMessage, StrategyManifest>>,
|
pub strategy: Arc<Plugin<StrategyEngineMessage, StrategyMessage, StrategyManifest>>,
|
||||||
pub risk: Arc<Plugin<RiskEngineMessage, RiskMessage, RiskManifest>>,
|
|
||||||
pub engine: Weak<Engine>,
|
pub engine: Weak<Engine>,
|
||||||
|
|
||||||
pub ws: WebSocket,
|
pub ws: WebSocket,
|
||||||
@@ -28,9 +27,8 @@ pub struct StrategyEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl StrategyEngine {
|
impl StrategyEngine {
|
||||||
pub async fn new(strategy_id: &str, risk_id: &str) -> tokio::io::Result<Self> {
|
pub async fn new(strategy_id: &str) -> tokio::io::Result<Self> {
|
||||||
let strategy = pulse_plugin(strategy_id)?;
|
let strategy = pulse_plugin(strategy_id)?;
|
||||||
let risk = pulse_plugin(risk_id)?;
|
|
||||||
|
|
||||||
let (strategy, strategy_manifest) = get_manifest_plugin_pair(
|
let (strategy, strategy_manifest) = get_manifest_plugin_pair(
|
||||||
&strategy,
|
&strategy,
|
||||||
@@ -38,15 +36,8 @@ impl StrategyEngine {
|
|||||||
&fs::read(strategy.join("strategy.toml")).await?,
|
&fs::read(strategy.join("strategy.toml")).await?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (risk, risk_manifest) = get_manifest_plugin_pair(
|
|
||||||
&risk,
|
|
||||||
&risk.join("risk.bash"),
|
|
||||||
&fs::read(risk.join("risk.toml")).await?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
strategy: Arc::new(Plugin::new(strategy, strategy_manifest)),
|
strategy: Arc::new(Plugin::new(strategy, strategy_manifest)),
|
||||||
risk: Arc::new(Plugin::new(risk, risk_manifest)),
|
|
||||||
engine: Weak::new(),
|
engine: Weak::new(),
|
||||||
ws: hypercore::mainnet_ws(),
|
ws: hypercore::mainnet_ws(),
|
||||||
subscriptions: Mutex::new(HashSet::new()),
|
subscriptions: Mutex::new(HashSet::new()),
|
||||||
@@ -87,7 +78,24 @@ impl StrategyEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Some(StrategyMessage::Signal(signal)) => {
|
Some(StrategyMessage::Signal(signal)) => {
|
||||||
self.risk.send(&RiskEngineMessage::Signal(signal)).await?;
|
match engine.execute_signal(&signal).await {
|
||||||
|
Ok(_) => engine.signals.lock().await.push(Ok(signal)),
|
||||||
|
Err(e) => {
|
||||||
|
engine.signals.lock().await.push(Err(signal));
|
||||||
|
|
||||||
|
engine
|
||||||
|
.terminal_server
|
||||||
|
.error("signal", &format!("Failed to execute signal: {e}"))
|
||||||
|
.await?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
engine
|
||||||
|
.terminal_server
|
||||||
|
.broadcast(TerminalServerMessage::SignalsUpdated(
|
||||||
|
engine.signals.lock().await.clone(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(StrategyMessage::Subscribe(subscription)) => {
|
Some(StrategyMessage::Subscribe(subscription)) => {
|
||||||
@@ -153,74 +161,10 @@ impl StrategyEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_risk(&self) -> tokio::io::Result<()> {
|
|
||||||
let engine = self
|
|
||||||
.engine
|
|
||||||
.upgrade()
|
|
||||||
.expect("Failed to upgrade engine (StrategyEngine)");
|
|
||||||
|
|
||||||
self.risk.send(&RiskEngineMessage::Initialize).await?;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
match self.risk.recv().await? {
|
|
||||||
None => {}
|
|
||||||
|
|
||||||
Some(RiskMessage::GetWatchList) => {
|
|
||||||
self.risk
|
|
||||||
.send(&&RiskEngineMessage::WatchList(
|
|
||||||
engine.watch_list.lock().await.clone().items,
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(RiskMessage::Log(mut log)) => {
|
|
||||||
log.name.insert_str(0, "risk::");
|
|
||||||
engine.terminal_server.log_raw(log).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(RiskMessage::Signal(ref sig @ RiskSignal::Approve(ref signal))) => {
|
|
||||||
match engine.execute_signal(signal).await {
|
|
||||||
Ok(_) => engine.signals.lock().await.push(Ok(sig.clone())),
|
|
||||||
Err(e) => {
|
|
||||||
engine.signals.lock().await.push(Err(sig.clone()));
|
|
||||||
|
|
||||||
engine
|
|
||||||
.terminal_server
|
|
||||||
.error("signal", &format!("Failed to execute signal: {e}"))
|
|
||||||
.await?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
engine
|
|
||||||
.terminal_server
|
|
||||||
.broadcast(TerminalServerMessage::SignalsUpdated(
|
|
||||||
engine.signals.lock().await.clone(),
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(RiskMessage::Signal(reject)) => {
|
|
||||||
engine.signals.lock().await.push(Ok(reject));
|
|
||||||
|
|
||||||
engine
|
|
||||||
.terminal_server
|
|
||||||
.broadcast(TerminalServerMessage::SignalsUpdated(
|
|
||||||
engine.signals.lock().await.clone(),
|
|
||||||
))
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn spawn(self: &Arc<Self>) {
|
pub async fn spawn(self: &Arc<Self>) {
|
||||||
let engine = self.clone();
|
let engine = self.clone();
|
||||||
|
|
||||||
tokio::spawn(async move { engine.run_strategy().await });
|
tokio::spawn(async move { engine.run_strategy().await });
|
||||||
|
|
||||||
let engine = self.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move { engine.run_risk().await });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn reload_strategy(self: &Arc<Self>, id: &str) -> tokio::io::Result<()> {
|
pub async fn reload_strategy(self: &Arc<Self>, id: &str) -> tokio::io::Result<()> {
|
||||||
@@ -239,23 +183,6 @@ impl StrategyEngine {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn reload_risk(self: &Arc<Self>, id: &str) -> tokio::io::Result<()> {
|
|
||||||
let plugin = pulse_plugin(id)?;
|
|
||||||
|
|
||||||
let (child, manifest) = get_manifest_plugin_pair(
|
|
||||||
&plugin,
|
|
||||||
&plugin.join("risk.bash"),
|
|
||||||
&fs::read(plugin.join("risk.toml")).await?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.risk.reload(child, manifest).await?;
|
|
||||||
|
|
||||||
let engine = self.clone();
|
|
||||||
tokio::spawn(async move { engine.run_risk().await });
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_manifest_plugin_pair<'de, M: serde::Deserialize<'de>>(
|
pub fn get_manifest_plugin_pair<'de, M: serde::Deserialize<'de>>(
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use hypersdk::hypercore::CandleInterval;
|
|||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub watchlist: Vec<String>,
|
pub watchlist: Vec<String>,
|
||||||
pub strategy: String,
|
pub strategy: String,
|
||||||
pub risk: String,
|
|
||||||
pub cooldown: CandleInterval,
|
pub cooldown: CandleInterval,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,7 +12,6 @@ impl Default for Config {
|
|||||||
Self {
|
Self {
|
||||||
watchlist: vec!["BTC".to_string(), "SOL".to_string(), "ETH".to_string()],
|
watchlist: vec!["BTC".to_string(), "SOL".to_string(), "ETH".to_string()],
|
||||||
strategy: String::new(),
|
strategy: String::new(),
|
||||||
risk: String::new(),
|
|
||||||
cooldown: CandleInterval::ThirtyMinutes,
|
cooldown: CandleInterval::ThirtyMinutes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ impl TerminalServer {
|
|||||||
id,
|
id,
|
||||||
pulse_sdk::terminal::TerminalServerMessage::StrategyUpdated(Strategy {
|
pulse_sdk::terminal::TerminalServerMessage::StrategyUpdated(Strategy {
|
||||||
strategy: engine.strategy.strategy.manifest.lock().await.clone(),
|
strategy: engine.strategy.strategy.manifest.lock().await.clone(),
|
||||||
risk: engine.strategy.risk.manifest.lock().await.clone(),
|
|
||||||
mode: Mode::Auto,
|
mode: Mode::Auto,
|
||||||
state: ItemState::Running,
|
state: ItemState::Running,
|
||||||
cooldown: engine.config.lock().await.cooldown,
|
cooldown: engine.config.lock().await.cooldown,
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ impl Formatted for EventLog {
|
|||||||
impl Formatted for SignalStatus {
|
impl Formatted for SignalStatus {
|
||||||
fn get_formatted(&self) -> Vec<String> {
|
fn get_formatted(&self) -> Vec<String> {
|
||||||
match self {
|
match self {
|
||||||
Ok(RiskSignal::Approve(signal)) => {
|
Ok(signal) => {
|
||||||
vec![
|
vec![
|
||||||
format!("\x1b[33mOK\x1b[0m"),
|
format!("\x1b[33mOK\x1b[0m"),
|
||||||
if matches!(signal.kind, Direction::Buy) {
|
if matches!(signal.kind, Direction::Buy) {
|
||||||
@@ -74,25 +74,8 @@ impl Formatted for SignalStatus {
|
|||||||
format!("\x1b[33mAPR {}\x1b[0m", signal.confidence),
|
format!("\x1b[33mAPR {}\x1b[0m", signal.confidence),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Ok(RiskSignal::Reject {
|
|
||||||
signal,
|
|
||||||
rejection_confidence,
|
|
||||||
reason,
|
|
||||||
}) => {
|
|
||||||
vec![
|
|
||||||
format!("\x1b[33mOK\x1b[0m"),
|
|
||||||
if matches!(signal.side, Direction::Buy) {
|
|
||||||
format!("\x1b[32mBUY\x1b[0m")
|
|
||||||
} else {
|
|
||||||
format!("\x1b[31mSELL\x1b[0m")
|
|
||||||
},
|
|
||||||
format!("\x1b[35m{}\x1b[0m", signal.symbol),
|
|
||||||
format!("\x1b[31mREJ {}\x1b[0m", rejection_confidence),
|
|
||||||
reason.to_owned(),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(RiskSignal::Approve(signal)) => {
|
Err(signal) => {
|
||||||
vec![
|
vec![
|
||||||
format!("\x1b[31mERR\x1b[0m"),
|
format!("\x1b[31mERR\x1b[0m"),
|
||||||
if matches!(signal.kind, Direction::Buy) {
|
if matches!(signal.kind, Direction::Buy) {
|
||||||
@@ -105,23 +88,6 @@ impl Formatted for SignalStatus {
|
|||||||
format!("\x1b[33mAPR {}\x1b[0m", signal.confidence),
|
format!("\x1b[33mAPR {}\x1b[0m", signal.confidence),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Err(RiskSignal::Reject {
|
|
||||||
signal,
|
|
||||||
rejection_confidence,
|
|
||||||
reason,
|
|
||||||
}) => {
|
|
||||||
vec![
|
|
||||||
format!("\x1b[31mERR\x1b[0m"),
|
|
||||||
if matches!(signal.side, Direction::Buy) {
|
|
||||||
format!("\x1b[32mBUY\x1b[0m")
|
|
||||||
} else {
|
|
||||||
format!("\x1b[31mSELL\x1b[0m")
|
|
||||||
},
|
|
||||||
format!("\x1b[35m{}\x1b[0m", signal.symbol),
|
|
||||||
format!("\x1b[31mREJ {}\x1b[0m", rejection_confidence),
|
|
||||||
reason.to_owned(),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,7 +257,7 @@ impl Formatted for Strategy {
|
|||||||
),
|
),
|
||||||
Triple(
|
Triple(
|
||||||
&format!("\x1b[97m{}\x1b[0m", self.strategy.name),
|
&format!("\x1b[97m{}\x1b[0m", self.strategy.name),
|
||||||
&format!("\x1b[93m{}\x1b[0m", self.risk.name),
|
&format!("\x1b[93m{}\x1b[0m", ""),
|
||||||
&format!("\x1b[90m{}\x1b[0m", self.strategy.version),
|
&format!("\x1b[90m{}\x1b[0m", self.strategy.version),
|
||||||
),
|
),
|
||||||
Triple("", "", ""),
|
Triple("", "", ""),
|
||||||
@@ -303,7 +269,7 @@ impl Formatted for Strategy {
|
|||||||
Triple(
|
Triple(
|
||||||
&self.mode.to_string(),
|
&self.mode.to_string(),
|
||||||
&self.state.to_string(),
|
&self.state.to_string(),
|
||||||
&format!("\x1b[90m{}\x1b[0m", self.risk.version),
|
&format!("\x1b[90m{}\x1b[0m", ""),
|
||||||
),
|
),
|
||||||
Triple("", "", ""),
|
Triple("", "", ""),
|
||||||
Triple(
|
Triple(
|
||||||
@@ -314,10 +280,10 @@ impl Formatted for Strategy {
|
|||||||
Triple(
|
Triple(
|
||||||
&format!(
|
&format!(
|
||||||
"\x1b[96m{}\x1b[0m (\x1b[90m{} rec\x1b[0m)",
|
"\x1b[96m{}\x1b[0m (\x1b[90m{} rec\x1b[0m)",
|
||||||
self.cooldown, self.risk.cooldown
|
self.cooldown, ""
|
||||||
),
|
),
|
||||||
&format!("\x1b[96m{:?}\x1b[0m", self.strategy.author),
|
&format!("\x1b[96m{:?}\x1b[0m", self.strategy.author),
|
||||||
&format!("\x1b[93m{}%\x1b[0m", self.risk.max_loss),
|
&format!("\x1b[93m{}%\x1b[0m", ""),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
.get_formatted()
|
.get_formatted()
|
||||||
|
|||||||
Reference in New Issue
Block a user