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:
parent
57758d3509
commit
20732387a6
3 changed files with 15 additions and 1 deletions
|
|
@ -223,6 +223,7 @@ impl BinanceClient {
|
||||||
let mut price_decimals = 2usize;
|
let mut price_decimals = 2usize;
|
||||||
let mut step_size = 0.01f64;
|
let mut step_size = 0.01f64;
|
||||||
let mut min_qty = 0.0f64;
|
let mut min_qty = 0.0f64;
|
||||||
|
let mut min_notional = 0.0f64;
|
||||||
|
|
||||||
for filter in filters {
|
for filter in filters {
|
||||||
match filter["filterType"].as_str() {
|
match filter["filterType"].as_str() {
|
||||||
|
|
@ -236,11 +237,14 @@ impl BinanceClient {
|
||||||
let tick = filter["tickSize"].as_str().unwrap_or("0.01");
|
let tick = filter["tickSize"].as_str().unwrap_or("0.01");
|
||||||
price_decimals = count_decimals(tick);
|
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
|
/// Tüm USDT spot işlem çiftlerini döner — public endpoint, API key gerektirmez
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ pub struct SymbolFilters {
|
||||||
pub price_decimals: usize,
|
pub price_decimals: usize,
|
||||||
pub step_size: f64,
|
pub step_size: f64,
|
||||||
pub min_qty: f64,
|
pub min_qty: f64,
|
||||||
|
pub min_notional: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolFilters {
|
impl SymbolFilters {
|
||||||
|
|
@ -70,6 +71,9 @@ impl SymbolFilters {
|
||||||
pub fn qty_is_valid(&self, qty: f64) -> bool {
|
pub fn qty_is_valid(&self, qty: f64) -> bool {
|
||||||
qty >= self.min_qty
|
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ı
|
/// Timeframe tanımları
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,12 @@ impl RedCandleStrategy {
|
||||||
quantity, filters.min_qty
|
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);
|
info!("[{}] Market alım | Miktar: {} | Fiyat tahmini: {:.6}", symbol, quantity, kline.close);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue