Risk config

This commit is contained in:
2026-07-31 20:13:31 +02:00
parent f9c67ce923
commit 7e4e264eb0
2 changed files with 91 additions and 1 deletions
+70 -1
View File
@@ -1,4 +1,4 @@
use hypersdk::hypercore::Side;
use hypersdk::{dec, hypercore::Side};
use rust_decimal::Decimal;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
@@ -30,6 +30,12 @@ pub enum Mode {
Manual,
}
#[derive(Debug, Clone)]
pub enum Allocation {
Fixed(Decimal),
Percent(Decimal),
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Signal {
pub symbol: String,
@@ -101,3 +107,66 @@ impl std::fmt::Display for ItemState {
}
}
}
impl<'de> serde::Deserialize<'de> for Allocation {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct AllocationVisitor;
impl<'de> serde::de::Visitor<'de> for AllocationVisitor {
type Value = Allocation;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a number or percentage string")
}
fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Allocation::Fixed(Decimal::from_f64_retain(value).unwrap()))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if let Some(percent) = value.strip_suffix('%') {
let value = percent.parse::<Decimal>().map_err(E::custom)?;
Ok(Allocation::Percent(value))
} else {
Err(E::custom("invalid allocation format"))
}
}
}
deserializer.deserialize_any(AllocationVisitor)
}
}
impl serde::Serialize for Allocation {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Allocation::Fixed(value) => serde::Serialize::serialize(value, serializer),
Allocation::Percent(value) => {
let s = format!("{}%", value);
serializer.serialize_str(&s)
}
}
}
}
impl Allocation {
pub fn get(&self, full_alloc: Decimal) -> Decimal {
match self {
Self::Fixed(f) => *f,
Self::Percent(p) => (*p / dec!(100.0)) * full_alloc,
}
}
}
+21
View File
@@ -1,10 +1,20 @@
use std::collections::HashMap;
use pulse_sdk::general::Allocation;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct RiskConfig {
pub risk_per_trade: Allocation,
pub max_open_positions: u32,
pub max_daily_loss: Allocation,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct Config {
pub description: Option<String>,
pub watchlist: Vec<String>,
pub strategy: String,
pub risk: RiskConfig,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
@@ -15,12 +25,23 @@ pub struct ConfigManager {
pub configs: HashMap<String, Config>,
}
impl Default for RiskConfig {
fn default() -> Self {
Self {
risk_per_trade: Allocation::Percent(10.into()),
max_daily_loss: Allocation::Percent(20.into()),
max_open_positions: 1,
}
}
}
impl Default for Config {
fn default() -> Self {
Self {
description: None,
watchlist: vec!["BTC".to_string(), "SOL".to_string(), "ETH".to_string()],
strategy: String::new(),
risk: Default::default(),
}
}
}