Market overview
This commit is contained in:
@@ -67,3 +67,37 @@ impl Widget for SpacedColumns {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpacedRows2(pub Vec<(LayoutItem, Box<dyn Widget>)>);
|
||||
|
||||
impl Widget for SpacedRows2 {
|
||||
fn render(&self, scope: &mut crate::render::RenderScope) {
|
||||
let alloc = scope.rect.allocate(&crate::layout::LayoutItem::Rows {
|
||||
unit: Percent(100),
|
||||
items: self.0.iter().map(|v| v.0.clone()).collect(),
|
||||
});
|
||||
|
||||
for i in 0..alloc.widgets.len() {
|
||||
let item = &self.0[i];
|
||||
|
||||
alloc.draw(i, &*item.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpacedColumns2(pub Vec<(LayoutItem, Box<dyn Widget>)>);
|
||||
|
||||
impl Widget for SpacedColumns2 {
|
||||
fn render(&self, scope: &mut crate::render::RenderScope) {
|
||||
let alloc = scope.rect.allocate(&crate::layout::LayoutItem::Columns {
|
||||
unit: Percent(100),
|
||||
items: self.0.iter().map(|v| v.0.clone()).collect(),
|
||||
});
|
||||
|
||||
for i in 0..alloc.widgets.len() {
|
||||
let item = &self.0[i];
|
||||
|
||||
alloc.draw(i, &*item.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-2
@@ -1,11 +1,29 @@
|
||||
use crate::types::{
|
||||
ActivePosition, EventLog, LogKind, MarketOverview, Signal, SignalKind, Status, WatchListItem,
|
||||
ActivePosition, Alert, AlertLevel, EventLog, LogKind, MarketOverview, Signal, SignalKind,
|
||||
Status, WatchListItem,
|
||||
};
|
||||
|
||||
pub trait Formatted {
|
||||
fn get_formatted(&self) -> Vec<String>;
|
||||
}
|
||||
|
||||
impl Formatted for Alert {
|
||||
fn get_formatted(&self) -> Vec<String> {
|
||||
vec![
|
||||
format!(
|
||||
"{}{:?}\x1b[0m",
|
||||
match &self.level {
|
||||
AlertLevel::L => "\x1b[34m",
|
||||
AlertLevel::M => "\x1b[33m",
|
||||
AlertLevel::H => "\x1b[31m",
|
||||
},
|
||||
self.level
|
||||
),
|
||||
self.message.clone(),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl Formatted for EventLog {
|
||||
fn get_formatted(&self) -> Vec<String> {
|
||||
vec![
|
||||
@@ -80,7 +98,19 @@ pub struct Property(&'static str, String);
|
||||
|
||||
impl Formatted for MarketOverview {
|
||||
fn get_formatted(&self) -> Vec<String> {
|
||||
vec![Property("Equity", format_f64(1.0))].get_formatted()
|
||||
vec![
|
||||
Property("TREND", format!("{:?}", self.trend)),
|
||||
Property("VOLATILITY", format!("{:?}", self.volatility)),
|
||||
Property(
|
||||
"PRESSURE",
|
||||
if self.pressure.is_sign_positive() {
|
||||
format!("\x1b[32m{:.3}\x1b[0m", self.pressure)
|
||||
} else {
|
||||
format!("\x1b[31m{:.3}\x1b[0m", self.pressure)
|
||||
},
|
||||
),
|
||||
]
|
||||
.get_formatted()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
-10
@@ -13,13 +13,13 @@ use pulse_ui::{
|
||||
align::End,
|
||||
input::{Input, InputState},
|
||||
outline::{Outline, VLine},
|
||||
spaced::SpacedColumns,
|
||||
spaced::{SpacedColumns, SpacedColumns2, SpacedRows2},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
formatting::{Formatted, apply_padding},
|
||||
types::{ActivePosition, EventLog, MarketOverview, Signal, Status, WatchListItem},
|
||||
types::{ActivePosition, Alert, EventLog, MarketOverview, Signal, Status, WatchListItem},
|
||||
};
|
||||
|
||||
pub struct PulseTradeApp {
|
||||
@@ -33,7 +33,7 @@ pub struct PulseTradeApp {
|
||||
}
|
||||
|
||||
impl App for PulseTradeApp {
|
||||
async fn init(&mut self, ctx: &pulse_ui::state::Context) {
|
||||
async fn init(&mut self, _ctx: &pulse_ui::state::Context) {
|
||||
let mut watch_list = self.watch_list.lock().await;
|
||||
|
||||
watch_list.push(WatchListItem {
|
||||
@@ -110,6 +110,23 @@ impl App for PulseTradeApp {
|
||||
name: "pulse.init",
|
||||
message: "We're still not done yet ;)".to_string(),
|
||||
});
|
||||
|
||||
let mut market_overview = self.market_overview.lock().await;
|
||||
|
||||
market_overview.alerts.push(Alert {
|
||||
level: types::AlertLevel::H,
|
||||
message: "BTC funding rate elevated".to_string(),
|
||||
});
|
||||
|
||||
market_overview.alerts.push(Alert {
|
||||
level: types::AlertLevel::M,
|
||||
message: "Market volatility increasing".to_string(),
|
||||
});
|
||||
|
||||
market_overview.alerts.push(Alert {
|
||||
level: types::AlertLevel::L,
|
||||
message: "ETH volatility returning to normal".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
async fn update(&mut self, ctx: &pulse_ui::state::Context, event: Box<dyn Any + Send + Sync>) {
|
||||
@@ -192,13 +209,14 @@ impl App for PulseTradeApp {
|
||||
.join("\n")
|
||||
)),
|
||||
),
|
||||
(
|
||||
LayoutItem::Widget(Size::Flex(1)),
|
||||
(LayoutItem::Widget(Size::Flex(1)), {
|
||||
let mo = self.market_overview.lock().await;
|
||||
Box::new(format![
|
||||
" MARKET OVERVIEW\n{}",
|
||||
apply_padding(self.market_overview.lock().await.get_formatted()).join("\n")
|
||||
]),
|
||||
),
|
||||
" MARKET OVERVIEW\n{}\n\n{}",
|
||||
apply_padding(mo.get_formatted()).join("\n"),
|
||||
apply_padding(mo.alerts.get_formatted(),).join("\n")
|
||||
])
|
||||
}),
|
||||
]),
|
||||
);
|
||||
|
||||
@@ -246,7 +264,12 @@ async fn main() {
|
||||
active_positions: ctx.use_state(Vec::new()),
|
||||
signals: ctx.use_state(Vec::new()),
|
||||
logs: ctx.use_state(Vec::new()),
|
||||
market_overview: ctx.use_state(MarketOverview {}),
|
||||
market_overview: ctx.use_state(MarketOverview {
|
||||
trend: types::MarketTrend::Bullish,
|
||||
volatility: types::Volatility::High,
|
||||
pressure: 0.324,
|
||||
alerts: Vec::new(),
|
||||
}),
|
||||
status: ctx.use_state(Status {
|
||||
feed: types::Feed::Connected,
|
||||
exchange: "Binance".to_string(),
|
||||
|
||||
+34
-1
@@ -10,7 +10,27 @@ pub struct ActivePosition {
|
||||
pub amount: f64,
|
||||
}
|
||||
|
||||
pub struct MarketOverview {}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum MarketTrend {
|
||||
Bullish,
|
||||
Bearish,
|
||||
Neutral,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Volatility {
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
}
|
||||
|
||||
pub struct MarketOverview {
|
||||
pub trend: MarketTrend,
|
||||
pub volatility: Volatility,
|
||||
pub pressure: f64,
|
||||
|
||||
pub alerts: Vec<Alert>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Feed {
|
||||
@@ -62,3 +82,16 @@ pub struct EventLog {
|
||||
pub name: &'static str,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum AlertLevel {
|
||||
H,
|
||||
M,
|
||||
L,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Alert {
|
||||
pub level: AlertLevel,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user