fix(mse): validate NOTIONAL filter before placing buy order

SymbolFilters now parses minNotional from Binance NOTIONAL filter.
strategy.rs checks qty*price >= minNotional before market_buy,
returning a descriptive error instead of letting Binance reject with -1013.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mukan Erkin TÖRÜK 2026-04-25 11:55:46 +03:00
parent 57758d3509
commit 20732387a6
3 changed files with 15 additions and 1 deletions

View file

@ -223,6 +223,7 @@ impl BinanceClient {
let mut price_decimals = 2usize;
let mut step_size = 0.01f64;
let mut min_qty = 0.0f64;
let mut min_notional = 0.0f64;
for filter in filters {
match filter["filterType"].as_str() {
@ -236,11 +237,14 @@ impl BinanceClient {
let tick = filter["tickSize"].as_str().unwrap_or("0.01");
price_decimals = count_decimals(tick);
}
Some("NOTIONAL") => {
min_notional = filter["minNotional"].as_str().unwrap_or("0").parse().unwrap_or(0.0);
}
_ => {}
}
}
Ok(SymbolFilters { qty_decimals, price_decimals, step_size, min_qty })
Ok(SymbolFilters { qty_decimals, price_decimals, step_size, min_qty, min_notional })
}
/// Tüm USDT spot işlem çiftlerini döner — public endpoint, API key gerektirmez

View file

@ -52,6 +52,7 @@ pub struct SymbolFilters {
pub price_decimals: usize,
pub step_size: f64,
pub min_qty: f64,
pub min_notional: f64,
}
impl SymbolFilters {
@ -70,6 +71,9 @@ impl SymbolFilters {
pub fn qty_is_valid(&self, qty: f64) -> bool {
qty >= self.min_qty
}
pub fn notional_is_valid(&self, qty: f64, price: f64) -> bool {
self.min_notional <= 0.0 || qty * price >= self.min_notional
}
}
/// Timeframe tanımları

View file

@ -38,6 +38,12 @@ impl RedCandleStrategy {
quantity, filters.min_qty
));
}
if !filters.notional_is_valid(qty_f, kline.close) {
return Err(anyhow::anyhow!(
"İşlem tutarı ({:.2} USDT) min notional ({} USDT) altında — USDT miktarını artır",
qty_f * kline.close, filters.min_notional
));
}
info!("[{}] Market alım | Miktar: {} | Fiyat tahmini: {:.6}", symbol, quantity, kline.close);