Initial commit: multi-symbol bot with backtest engine and RSI trend strategy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
"""
|
||||
Position sizing and trade-permission checks.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import math
|
||||
from datetime import date
|
||||
|
||||
from . import config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
MIN_LOT = 0.01
|
||||
MAX_LOT = 100.0
|
||||
|
||||
|
||||
def calculate_lot_size(
|
||||
symbol_info: dict,
|
||||
balance: float,
|
||||
entry_price: float,
|
||||
sl_price: float,
|
||||
) -> float:
|
||||
"""Risk `config.RISK_PER_TRADE` fraction of balance on a single trade."""
|
||||
risk_amount = balance * config.RISK_PER_TRADE
|
||||
|
||||
tick_value = symbol_info["trade_tick_value"]
|
||||
tick_size = symbol_info["trade_tick_size"]
|
||||
if tick_value == 0 or tick_size == 0:
|
||||
return MIN_LOT
|
||||
|
||||
pip_size = tick_size * 10
|
||||
pip_value = tick_value * (pip_size / tick_size)
|
||||
dist_pips = abs(entry_price - sl_price) / pip_size
|
||||
|
||||
if dist_pips < config.MIN_SL_PIPS:
|
||||
logger.warning("SL too tight for %s: %.1f pips — skipping",
|
||||
symbol_info.get("name"), dist_pips)
|
||||
return 0.0
|
||||
|
||||
lot = risk_amount / (pip_value * dist_pips)
|
||||
lot = max(MIN_LOT, min(MAX_LOT, lot))
|
||||
step = symbol_info.get("volume_step", 0.01)
|
||||
lot = math.floor(lot / step) * step
|
||||
return round(lot, 2)
|
||||
|
||||
|
||||
def can_trade(account_info: dict, open_positions: list[dict], state: dict) -> bool:
|
||||
if len(open_positions) >= config.MAX_POSITIONS:
|
||||
logger.debug("Max positions reached (%d)", config.MAX_POSITIONS)
|
||||
return False
|
||||
|
||||
today = date.today().isoformat()
|
||||
daily_pnl = state.get("daily_pnl", {}).get(today, 0.0)
|
||||
balance = account_info.get("balance", 1.0)
|
||||
if daily_pnl / balance < -config.MAX_DAILY_LOSS:
|
||||
logger.warning("Daily loss limit hit: %.1f%% of balance",
|
||||
-daily_pnl / balance * 100)
|
||||
return False
|
||||
|
||||
return True
|
||||
Reference in New Issue
Block a user