Better signal formatting
This commit is contained in:
@@ -32,89 +32,91 @@ impl Engine {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let order_ids = self.risk_engine.create_order().await?;
|
||||
let order_ids = self.risk_engine.create_order(signal).await?;
|
||||
|
||||
let order = BatchOrder {
|
||||
orders: vec![
|
||||
OrderRequest {
|
||||
asset: asset_id,
|
||||
is_buy: matches!(signal.side, Side::Bid),
|
||||
limit_px: signal.entry_price,
|
||||
sz: 0.into(),
|
||||
reduce_only: false,
|
||||
order_type: OrderTypePlacement::Limit {
|
||||
tif: TimeInForce::Gtc,
|
||||
},
|
||||
cloid: order_ids.entry,
|
||||
},
|
||||
OrderRequest {
|
||||
asset: asset_id,
|
||||
is_buy: matches!(signal.side, Side::Bid),
|
||||
limit_px: signal.entry_price,
|
||||
sz: 0.into(),
|
||||
reduce_only: true,
|
||||
order_type: OrderTypePlacement::Trigger {
|
||||
is_market: true,
|
||||
trigger_px: signal.take_profit,
|
||||
tpsl: hypercore::TpSl::Tp,
|
||||
},
|
||||
cloid: order_ids.take_profit,
|
||||
},
|
||||
OrderRequest {
|
||||
asset: asset_id,
|
||||
is_buy: matches!(signal.side, Side::Bid),
|
||||
limit_px: signal.entry_price,
|
||||
sz: 0.into(),
|
||||
reduce_only: true,
|
||||
order_type: OrderTypePlacement::Trigger {
|
||||
is_market: true,
|
||||
trigger_px: signal.stop_loss,
|
||||
tpsl: hypercore::TpSl::Sl,
|
||||
},
|
||||
cloid: order_ids.stop_loss,
|
||||
},
|
||||
],
|
||||
grouping: hypercore::OrderGrouping::Na,
|
||||
builder: None,
|
||||
};
|
||||
println!("{order_ids:?}");
|
||||
|
||||
let nonce = chrono::Utc::now().timestamp_millis() as u64;
|
||||
// let order = BatchOrder {
|
||||
// orders: vec![
|
||||
// OrderRequest {
|
||||
// asset: asset_id,
|
||||
// is_buy: matches!(signal.side, Side::Bid),
|
||||
// limit_px: signal.entry_price,
|
||||
// sz: 0.into(),
|
||||
// reduce_only: false,
|
||||
// order_type: OrderTypePlacement::Limit {
|
||||
// tif: TimeInForce::Gtc,
|
||||
// },
|
||||
// cloid: order_ids.entry,
|
||||
// },
|
||||
// OrderRequest {
|
||||
// asset: asset_id,
|
||||
// is_buy: matches!(signal.side, Side::Bid),
|
||||
// limit_px: signal.entry_price,
|
||||
// sz: 0.into(),
|
||||
// reduce_only: true,
|
||||
// order_type: OrderTypePlacement::Trigger {
|
||||
// is_market: true,
|
||||
// trigger_px: signal.take_profit,
|
||||
// tpsl: hypercore::TpSl::Tp,
|
||||
// },
|
||||
// cloid: order_ids.take_profit,
|
||||
// },
|
||||
// OrderRequest {
|
||||
// asset: asset_id,
|
||||
// is_buy: matches!(signal.side, Side::Bid),
|
||||
// limit_px: signal.entry_price,
|
||||
// sz: 0.into(),
|
||||
// reduce_only: true,
|
||||
// order_type: OrderTypePlacement::Trigger {
|
||||
// is_market: true,
|
||||
// trigger_px: signal.stop_loss,
|
||||
// tpsl: hypercore::TpSl::Sl,
|
||||
// },
|
||||
// cloid: order_ids.stop_loss,
|
||||
// },
|
||||
// ],
|
||||
// grouping: hypercore::OrderGrouping::Na,
|
||||
// builder: None,
|
||||
// };
|
||||
|
||||
match client
|
||||
.place(&acc.private_key.0, order, nonce, None, None)
|
||||
.await
|
||||
{
|
||||
Ok(o) if o.iter().any(|o| matches!(o, OrderResponseStatus::Error(_))) => {
|
||||
self.risk_engine.order_placed(order_ids).await;
|
||||
}
|
||||
// let nonce = chrono::Utc::now().timestamp_millis() as u64;
|
||||
|
||||
Ok(e) => {
|
||||
self.terminal_server
|
||||
.error(
|
||||
"self::order",
|
||||
&format!(
|
||||
"order rejected: {}",
|
||||
e.into_iter()
|
||||
.filter_map(|res| {
|
||||
if let OrderResponseStatus::Error(e) = res {
|
||||
Some(e)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
// match client
|
||||
// .place(&acc.private_key.0, order, nonce, None, None)
|
||||
// .await
|
||||
// {
|
||||
// Ok(o) if o.iter().any(|o| matches!(o, OrderResponseStatus::Error(_))) => {
|
||||
// self.risk_engine.order_placed(order_ids).await;
|
||||
// }
|
||||
|
||||
Err(e) => {
|
||||
self.terminal_server
|
||||
.error("self::order", &e.to_string())
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
// Ok(e) => {
|
||||
// self.terminal_server
|
||||
// .error(
|
||||
// "self::order",
|
||||
// &format!(
|
||||
// "order rejected: {}",
|
||||
// e.into_iter()
|
||||
// .filter_map(|res| {
|
||||
// if let OrderResponseStatus::Error(e) = res {
|
||||
// Some(e)
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// })
|
||||
// .collect::<Vec<_>>()
|
||||
// .join(", ")
|
||||
// ),
|
||||
// )
|
||||
// .await?;
|
||||
// }
|
||||
|
||||
// Err(e) => {
|
||||
// self.terminal_server
|
||||
// .error("self::order", &e.to_string())
|
||||
// .await?;
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
self.terminal_server
|
||||
.error("Engine::order", "Unable to get active account")
|
||||
|
||||
+20
-22
@@ -14,22 +14,13 @@ use tokio::sync::Mutex;
|
||||
use crate::{engine::Engine, store::config::RiskConfig};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OrderIds {
|
||||
pub struct EngineOrder {
|
||||
pub risk_equity: Decimal,
|
||||
pub size: Decimal,
|
||||
|
||||
pub entry: Cloid,
|
||||
pub take_profit: Cloid,
|
||||
pub stop_loss: Cloid,
|
||||
pub risk_equity: Decimal,
|
||||
}
|
||||
|
||||
impl OrderIds {
|
||||
pub fn new(risk_equity: Decimal) -> Self {
|
||||
Self {
|
||||
entry: Cloid::random(),
|
||||
take_profit: Cloid::random(),
|
||||
stop_loss: Cloid::random(),
|
||||
risk_equity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RiskState {
|
||||
@@ -40,7 +31,7 @@ pub struct RiskState {
|
||||
|
||||
pub struct RiskEngine {
|
||||
// Orders made by the engine
|
||||
pub orders: Mutex<Vec<OrderIds>>,
|
||||
pub orders: Mutex<Vec<EngineOrder>>,
|
||||
pub handle: Mutex<ConnectionHandle>,
|
||||
pub state: Mutex<RiskState>,
|
||||
pub engine: Weak<Engine>,
|
||||
@@ -154,18 +145,25 @@ impl RiskEngine {
|
||||
Ok(under_max_losses)
|
||||
}
|
||||
|
||||
pub async fn create_order(&self) -> tokio::io::Result<OrderIds> {
|
||||
pub async fn create_order(&self, signal: &Signal) -> tokio::io::Result<EngineOrder> {
|
||||
let state = self.state.lock().await;
|
||||
|
||||
Ok(OrderIds::new(
|
||||
self.get_risk_config()
|
||||
.await?
|
||||
.risk_per_trade
|
||||
.get(state.starting_equity),
|
||||
))
|
||||
let risk = self
|
||||
.get_risk_config()
|
||||
.await?
|
||||
.risk_per_trade
|
||||
.get(state.starting_equity);
|
||||
|
||||
Ok(EngineOrder {
|
||||
entry: Cloid::random(),
|
||||
take_profit: Cloid::random(),
|
||||
stop_loss: Cloid::random(),
|
||||
risk_equity: risk,
|
||||
size: risk / (signal.entry_price - signal.stop_loss).abs(),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn order_placed(&self, order: OrderIds) {
|
||||
pub async fn order_placed(&self, order: EngineOrder) {
|
||||
self.orders.lock().await.push(order);
|
||||
}
|
||||
|
||||
|
||||
+17
-18
@@ -54,31 +54,22 @@ impl Formatted for EventLog {
|
||||
impl Formatted for SignalStatus {
|
||||
fn get_formatted(&self) -> Vec<String> {
|
||||
match self {
|
||||
Ok(signal) => {
|
||||
Ok(signal) | Err(signal) => {
|
||||
vec![
|
||||
format!("\x1b[33mOK\x1b[0m"),
|
||||
if matches!(signal.side, Side::Ask) {
|
||||
if matches!(self, Ok(_)) {
|
||||
format!("\x1b[34mOK\x1b[0m")
|
||||
} else {
|
||||
format!("\x1b[31mREJ\x1b[0m")
|
||||
},
|
||||
if matches!(signal.side, Side::Bid) {
|
||||
format!("\x1b[32mBUY\x1b[0m")
|
||||
} else {
|
||||
format!("\x1b[31mSELL\x1b[0m")
|
||||
},
|
||||
format_symbol(&signal.symbol),
|
||||
format_usd(signal.entry_price.as_f64()),
|
||||
format!("\x1b[33mAPR {}\x1b[0m", signal.confidence),
|
||||
]
|
||||
}
|
||||
|
||||
Err(signal) => {
|
||||
vec![
|
||||
format!("\x1b[31mERR\x1b[0m"),
|
||||
if matches!(signal.side, Side::Ask) {
|
||||
format!("\x1b[32mBUY\x1b[0m")
|
||||
} else {
|
||||
format!("\x1b[31mSELL\x1b[0m")
|
||||
},
|
||||
format_symbol(&signal.symbol),
|
||||
format_usd(signal.entry_price.as_f64()),
|
||||
format!("\x1b[33mAPR {}\x1b[0m", signal.confidence),
|
||||
format_usd(signal.take_profit.as_f64()),
|
||||
format_usd_reverse(signal.stop_loss.as_f64()),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -274,6 +265,14 @@ pub fn format_usd(value: f64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_usd_reverse(value: f64) -> String {
|
||||
if value.is_sign_positive() {
|
||||
format!("\x1b[31m${}\x1b[0m", format_f64(value))
|
||||
} else {
|
||||
format!("\x1b[32m${}\x1b[0m", format_f64(value))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_f64(value: f64) -> String {
|
||||
let abs = value.abs();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user