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::{
|
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
@@ -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
@@ -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,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user