Expand platform strategy runtime helpers
This commit is contained in:
@@ -115,18 +115,34 @@ struct DayExpressionState {
|
||||
signal_ma5: f64,
|
||||
signal_ma10: f64,
|
||||
signal_ma20: f64,
|
||||
cash: f64,
|
||||
market_value: f64,
|
||||
total_equity: f64,
|
||||
current_exposure: f64,
|
||||
position_count: i64,
|
||||
max_positions: i64,
|
||||
refresh_rate: i64,
|
||||
year: i64,
|
||||
month: i64,
|
||||
day_of_month: i64,
|
||||
weekday: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct StockExpressionState {
|
||||
market_cap: f64,
|
||||
free_float_cap: f64,
|
||||
pe_ttm: f64,
|
||||
turnover_ratio: f64,
|
||||
effective_turnover_ratio: f64,
|
||||
open: f64,
|
||||
close: f64,
|
||||
last: f64,
|
||||
prev_close: f64,
|
||||
upper_limit: f64,
|
||||
lower_limit: f64,
|
||||
price_tick: f64,
|
||||
round_lot: i64,
|
||||
paused: bool,
|
||||
is_st: bool,
|
||||
is_kcb: bool,
|
||||
@@ -166,6 +182,23 @@ impl PlatformExprStrategy {
|
||||
engine.register_fn("abs", |value: f64| value.abs());
|
||||
engine.register_fn("min", |lhs: f64, rhs: f64| lhs.min(rhs));
|
||||
engine.register_fn("max", |lhs: f64, rhs: f64| lhs.max(rhs));
|
||||
engine.register_fn("sqrt", |value: f64| value.sqrt());
|
||||
engine.register_fn("pow", |lhs: f64, rhs: f64| lhs.powf(rhs));
|
||||
engine.register_fn("log", |value: f64| value.ln());
|
||||
engine.register_fn("exp", |value: f64| value.exp());
|
||||
engine.register_fn("clamp", |value: f64, low: f64, high: f64| value.clamp(low, high));
|
||||
engine.register_fn("between", |value: f64, low: f64, high: f64| value >= low && value <= high);
|
||||
engine.register_fn("nz", |value: f64, fallback: f64| if value.is_finite() { value } else { fallback });
|
||||
engine.register_fn("safe_div", |lhs: f64, rhs: f64, fallback: f64| {
|
||||
if rhs.abs() <= f64::EPSILON {
|
||||
fallback
|
||||
} else {
|
||||
lhs / rhs
|
||||
}
|
||||
});
|
||||
engine.register_fn("iff", |condition: bool, when_true: Dynamic, when_false: Dynamic| {
|
||||
if condition { when_true } else { when_false }
|
||||
});
|
||||
Self { config, engine }
|
||||
}
|
||||
|
||||
@@ -527,6 +560,10 @@ impl PlatformExprStrategy {
|
||||
.data
|
||||
.market_decision_close_moving_average(date, &self.config.signal_symbol, 20)
|
||||
.unwrap_or(benchmark_ma10);
|
||||
let cash = ctx.portfolio.cash();
|
||||
let market_value = ctx.portfolio.positions().values().map(|position| position.market_value()).sum::<f64>();
|
||||
let total_equity = cash + market_value;
|
||||
let current_exposure = if total_equity > 0.0 { market_value / total_equity } else { 0.0 };
|
||||
|
||||
Ok(DayExpressionState {
|
||||
signal_close,
|
||||
@@ -539,6 +576,17 @@ impl PlatformExprStrategy {
|
||||
signal_ma5: benchmark_ma5,
|
||||
signal_ma10: benchmark_ma10,
|
||||
signal_ma20: benchmark_ma20,
|
||||
cash,
|
||||
market_value,
|
||||
total_equity,
|
||||
current_exposure,
|
||||
position_count: ctx.portfolio.positions().len() as i64,
|
||||
max_positions: self.config.max_positions as i64,
|
||||
refresh_rate: self.config.refresh_rate as i64,
|
||||
year: date.year() as i64,
|
||||
month: date.month() as i64,
|
||||
day_of_month: date.day() as i64,
|
||||
weekday: date.weekday().number_from_monday() as i64,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -551,6 +599,7 @@ impl PlatformExprStrategy {
|
||||
let market = ctx.data.require_market(date, symbol)?;
|
||||
let factor = ctx.data.require_factor(date, symbol)?;
|
||||
let candidate = ctx.data.require_candidate(date, symbol)?;
|
||||
let instrument = ctx.data.instrument(symbol);
|
||||
let stock_ma_short = ctx
|
||||
.data
|
||||
.market_decision_close_moving_average(date, symbol, self.config.stock_short_ma_days)
|
||||
@@ -579,12 +628,17 @@ impl PlatformExprStrategy {
|
||||
Ok(StockExpressionState {
|
||||
market_cap: factor.market_cap_bn,
|
||||
free_float_cap: factor.free_float_cap_bn,
|
||||
pe_ttm: factor.pe_ttm,
|
||||
turnover_ratio: factor.turnover_ratio.unwrap_or(0.0),
|
||||
effective_turnover_ratio: factor.effective_turnover_ratio.unwrap_or(0.0),
|
||||
open: market.day_open,
|
||||
close: market.close,
|
||||
last: market.last_price,
|
||||
prev_close: market.prev_close,
|
||||
upper_limit: market.upper_limit,
|
||||
lower_limit: market.lower_limit,
|
||||
price_tick: market.price_tick,
|
||||
round_lot: instrument.map(|item| item.effective_round_lot()).unwrap_or(100) as i64,
|
||||
paused: market.paused || candidate.is_paused,
|
||||
is_st: candidate.is_st || self.special_name(ctx, symbol),
|
||||
is_kcb: candidate.is_kcb,
|
||||
@@ -619,9 +673,24 @@ impl PlatformExprStrategy {
|
||||
scope.push("benchmark_ma20", day.benchmark_ma20);
|
||||
scope.push("benchmark_ma_short", day.benchmark_ma_short);
|
||||
scope.push("benchmark_ma_long", day.benchmark_ma_long);
|
||||
scope.push("cash", day.cash);
|
||||
scope.push("available_cash", day.cash);
|
||||
scope.push("market_value", day.market_value);
|
||||
scope.push("total_equity", day.total_equity);
|
||||
scope.push("current_exposure", day.current_exposure);
|
||||
scope.push("position_count", day.position_count);
|
||||
scope.push("max_positions", day.max_positions);
|
||||
scope.push("refresh_rate", day.refresh_rate);
|
||||
scope.push("year", day.year);
|
||||
scope.push("month", day.month);
|
||||
scope.push("day_of_month", day.day_of_month);
|
||||
scope.push("weekday", day.weekday);
|
||||
if let Some(stock) = stock {
|
||||
scope.push("market_cap", stock.market_cap);
|
||||
scope.push("free_float_cap", stock.free_float_cap);
|
||||
scope.push("pe_ttm", stock.pe_ttm);
|
||||
scope.push("turnover_ratio", stock.turnover_ratio);
|
||||
scope.push("effective_turnover_ratio", stock.effective_turnover_ratio);
|
||||
scope.push("open", stock.open);
|
||||
scope.push("close", stock.close);
|
||||
scope.push("last", stock.last);
|
||||
@@ -629,6 +698,8 @@ impl PlatformExprStrategy {
|
||||
scope.push("prev_close", stock.prev_close);
|
||||
scope.push("upper_limit", stock.upper_limit);
|
||||
scope.push("lower_limit", stock.lower_limit);
|
||||
scope.push("price_tick", stock.price_tick);
|
||||
scope.push("round_lot", stock.round_lot);
|
||||
scope.push("paused", stock.paused);
|
||||
scope.push("is_st", stock.is_st);
|
||||
scope.push("is_kcb", stock.is_kcb);
|
||||
|
||||
Reference in New Issue
Block a user