Market overview

This commit is contained in:
2026-07-15 21:39:08 +02:00
parent e5086439a1
commit a4f8e07be6
4 changed files with 133 additions and 13 deletions
+34
View File
@@ -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
View File
@@ -1,11 +1,29 @@
use crate::types::{ use crate::types::{
ActivePosition, EventLog, LogKind, MarketOverview, Signal, SignalKind, Status, WatchListItem, ActivePosition, Alert, AlertLevel, EventLog, LogKind, MarketOverview, Signal, SignalKind,
Status, WatchListItem,
}; };
pub trait Formatted { pub trait Formatted {
fn get_formatted(&self) -> Vec<String>; 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 { impl Formatted for EventLog {
fn get_formatted(&self) -> Vec<String> { fn get_formatted(&self) -> Vec<String> {
vec![ vec![
@@ -80,7 +98,19 @@ pub struct Property(&'static str, String);
impl Formatted for MarketOverview { impl Formatted for MarketOverview {
fn get_formatted(&self) -> Vec<String> { 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
View File
@@ -13,13 +13,13 @@ use pulse_ui::{
align::End, align::End,
input::{Input, InputState}, input::{Input, InputState},
outline::{Outline, VLine}, outline::{Outline, VLine},
spaced::SpacedColumns, spaced::{SpacedColumns, SpacedColumns2, SpacedRows2},
}, },
}; };
use crate::{ use crate::{
formatting::{Formatted, apply_padding}, formatting::{Formatted, apply_padding},
types::{ActivePosition, EventLog, MarketOverview, Signal, Status, WatchListItem}, types::{ActivePosition, Alert, EventLog, MarketOverview, Signal, Status, WatchListItem},
}; };
pub struct PulseTradeApp { pub struct PulseTradeApp {
@@ -33,7 +33,7 @@ pub struct PulseTradeApp {
} }
impl App for 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; let mut watch_list = self.watch_list.lock().await;
watch_list.push(WatchListItem { watch_list.push(WatchListItem {
@@ -110,6 +110,23 @@ impl App for PulseTradeApp {
name: "pulse.init", name: "pulse.init",
message: "We're still not done yet ;)".to_string(), 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>) { 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") .join("\n")
)), )),
), ),
( (LayoutItem::Widget(Size::Flex(1)), {
LayoutItem::Widget(Size::Flex(1)), let mo = self.market_overview.lock().await;
Box::new(format![ Box::new(format![
" MARKET OVERVIEW\n{}", " MARKET OVERVIEW\n{}\n\n{}",
apply_padding(self.market_overview.lock().await.get_formatted()).join("\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()), active_positions: ctx.use_state(Vec::new()),
signals: ctx.use_state(Vec::new()), signals: ctx.use_state(Vec::new()),
logs: 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 { status: ctx.use_state(Status {
feed: types::Feed::Connected, feed: types::Feed::Connected,
exchange: "Binance".to_string(), exchange: "Binance".to_string(),
+34 -1
View File
@@ -10,7 +10,27 @@ pub struct ActivePosition {
pub amount: f64, 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)] #[derive(Debug, Clone, Copy)]
pub enum Feed { pub enum Feed {
@@ -62,3 +82,16 @@ pub struct EventLog {
pub name: &'static str, pub name: &'static str,
pub message: String, 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,
}