feat: add multi-symbol config (symbols list, correlation_symbols, max_same_direction)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
BINANCE_API_KEY=
|
BINANCE_API_KEY=
|
||||||
BINANCE_API_SECRET=
|
BINANCE_API_SECRET=
|
||||||
SYMBOL=XRPUSDT
|
SYMBOLS=XRPUSDT
|
||||||
|
CORRELATION_SYMBOLS=BTCUSDT,ETHUSDT
|
||||||
LEVERAGE=10
|
LEVERAGE=10
|
||||||
RISK_PER_TRADE=0.02
|
RISK_PER_TRADE=0.02
|
||||||
DISCORD_WEBHOOK_URL=
|
DISCORD_WEBHOOK_URL=
|
||||||
ML_THRESHOLD=0.55
|
ML_THRESHOLD=0.55
|
||||||
|
MAX_SAME_DIRECTION=2
|
||||||
BINANCE_TESTNET_API_KEY=
|
BINANCE_TESTNET_API_KEY=
|
||||||
BINANCE_TESTNET_API_SECRET=
|
BINANCE_TESTNET_API_SECRET=
|
||||||
@@ -10,8 +10,11 @@ class Config:
|
|||||||
api_key: str = ""
|
api_key: str = ""
|
||||||
api_secret: str = ""
|
api_secret: str = ""
|
||||||
symbol: str = "XRPUSDT"
|
symbol: str = "XRPUSDT"
|
||||||
|
symbols: list = None
|
||||||
|
correlation_symbols: list = None
|
||||||
leverage: int = 10
|
leverage: int = 10
|
||||||
max_positions: int = 3
|
max_positions: int = 3
|
||||||
|
max_same_direction: int = 2
|
||||||
stop_loss_pct: float = 0.015 # 1.5%
|
stop_loss_pct: float = 0.015 # 1.5%
|
||||||
take_profit_pct: float = 0.045 # 4.5% (3:1 RR)
|
take_profit_pct: float = 0.045 # 4.5% (3:1 RR)
|
||||||
trailing_stop_pct: float = 0.01 # 1%
|
trailing_stop_pct: float = 0.01 # 1%
|
||||||
@@ -31,3 +34,15 @@ class Config:
|
|||||||
self.margin_min_ratio = float(os.getenv("MARGIN_MIN_RATIO", "0.20"))
|
self.margin_min_ratio = float(os.getenv("MARGIN_MIN_RATIO", "0.20"))
|
||||||
self.margin_decay_rate = float(os.getenv("MARGIN_DECAY_RATE", "0.0006"))
|
self.margin_decay_rate = float(os.getenv("MARGIN_DECAY_RATE", "0.0006"))
|
||||||
self.ml_threshold = float(os.getenv("ML_THRESHOLD", "0.55"))
|
self.ml_threshold = float(os.getenv("ML_THRESHOLD", "0.55"))
|
||||||
|
self.max_same_direction = int(os.getenv("MAX_SAME_DIRECTION", "2"))
|
||||||
|
|
||||||
|
# symbols: SYMBOLS 환경변수 우선, 없으면 SYMBOL에서 변환
|
||||||
|
symbols_env = os.getenv("SYMBOLS", "")
|
||||||
|
if symbols_env:
|
||||||
|
self.symbols = [s.strip() for s in symbols_env.split(",") if s.strip()]
|
||||||
|
else:
|
||||||
|
self.symbols = [self.symbol]
|
||||||
|
|
||||||
|
# correlation_symbols
|
||||||
|
corr_env = os.getenv("CORRELATION_SYMBOLS", "BTCUSDT,ETHUSDT")
|
||||||
|
self.correlation_symbols = [s.strip() for s in corr_env.split(",") if s.strip()]
|
||||||
|
|||||||
@@ -19,3 +19,32 @@ def test_config_dynamic_margin_params():
|
|||||||
assert cfg.margin_max_ratio == 0.50
|
assert cfg.margin_max_ratio == 0.50
|
||||||
assert cfg.margin_min_ratio == 0.20
|
assert cfg.margin_min_ratio == 0.20
|
||||||
assert cfg.margin_decay_rate == 0.0006
|
assert cfg.margin_decay_rate == 0.0006
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_loads_symbols_list():
|
||||||
|
"""SYMBOLS 환경변수로 쉼표 구분 리스트를 로드한다."""
|
||||||
|
os.environ["SYMBOLS"] = "XRPUSDT,TRXUSDT,DOGEUSDT"
|
||||||
|
os.environ.pop("SYMBOL", None)
|
||||||
|
cfg = Config()
|
||||||
|
assert cfg.symbols == ["XRPUSDT", "TRXUSDT", "DOGEUSDT"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_fallback_to_symbol():
|
||||||
|
"""SYMBOLS 미설정 시 SYMBOL에서 1개짜리 리스트로 변환한다."""
|
||||||
|
os.environ.pop("SYMBOLS", None)
|
||||||
|
os.environ["SYMBOL"] = "XRPUSDT"
|
||||||
|
cfg = Config()
|
||||||
|
assert cfg.symbols == ["XRPUSDT"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_correlation_symbols():
|
||||||
|
"""상관관계 심볼 로드."""
|
||||||
|
os.environ["CORRELATION_SYMBOLS"] = "BTCUSDT,ETHUSDT"
|
||||||
|
cfg = Config()
|
||||||
|
assert cfg.correlation_symbols == ["BTCUSDT", "ETHUSDT"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_max_same_direction_default():
|
||||||
|
"""동일 방향 최대 수 기본값 2."""
|
||||||
|
cfg = Config()
|
||||||
|
assert cfg.max_same_direction == 2
|
||||||
|
|||||||
Reference in New Issue
Block a user