deleted
This commit is contained in:
2
position_logic/__init__.py
Normal file
2
position_logic/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
# This file can be empty.
|
||||
# It tells Python that 'position_logic' is a directory containing modules.
|
||||
31
position_logic/base_logic.py
Normal file
31
position_logic/base_logic.py
Normal file
@ -0,0 +1,31 @@
|
||||
from abc import ABC, abstractmethod
|
||||
import logging
|
||||
|
||||
class BasePositionLogic(ABC):
|
||||
"""
|
||||
Abstract base class for all strategy-specific position logic.
|
||||
Defines the interface for how the PositionManager interacts with logic modules.
|
||||
"""
|
||||
def __init__(self, strategy_name: str, send_order_callback, log_trade_callback):
|
||||
self.strategy_name = strategy_name
|
||||
self.send_order = send_order_callback
|
||||
self.log_trade = log_trade_callback
|
||||
logging.info(f"Initialized position logic for '{strategy_name}'")
|
||||
|
||||
@abstractmethod
|
||||
def handle_signal(self, signal_data: dict, current_strategy_positions: dict) -> dict:
|
||||
"""
|
||||
The core logic method. This is called by the PositionManager when a
|
||||
new signal arrives for this strategy.
|
||||
|
||||
Args:
|
||||
signal_data: The full signal dictionary from the strategy.
|
||||
current_strategy_positions: A dict of this strategy's current positions,
|
||||
keyed by coin (e.g., {"BTC": {"side": "long", ...}}).
|
||||
|
||||
Returns:
|
||||
A dictionary representing the new state for the *specific coin* in the
|
||||
signal (e.g., {"side": "long", "size": 0.1}).
|
||||
Return None to indicate the position for this coin should be closed/removed.
|
||||
"""
|
||||
pass
|
||||
83
position_logic/default_flip_logic.py
Normal file
83
position_logic/default_flip_logic.py
Normal file
@ -0,0 +1,83 @@
|
||||
import logging
|
||||
from position_logic.base_logic import BasePositionLogic
|
||||
|
||||
class DefaultFlipLogic(BasePositionLogic):
|
||||
"""
|
||||
The standard "flip-on-signal" logic used by most simple strategies
|
||||
(SMA, MA Cross, and even the per-coin Copy Trader signals).
|
||||
|
||||
- BUY signal: Closes any short, opens a long.
|
||||
- SELL signal: Closes any long, opens a short.
|
||||
- FLAT signal: Closes any open position.
|
||||
"""
|
||||
def handle_signal(self, signal_data: dict, current_strategy_positions: dict) -> dict:
|
||||
"""
|
||||
Processes a BUY, SELL, or FLAT signal and issues the necessary orders
|
||||
to flip or open a position.
|
||||
"""
|
||||
name = self.strategy_name
|
||||
params = signal_data['config']['parameters']
|
||||
coin = signal_data['coin']
|
||||
desired_signal = signal_data['signal']
|
||||
signal_price = signal_data.get('signal_price', 0)
|
||||
|
||||
size = params.get('size')
|
||||
leverage_long = int(params.get('leverage_long', 2))
|
||||
leverage_short = int(params.get('leverage_short', 2))
|
||||
agent_name = signal_data['config'].get("agent", "default").lower()
|
||||
|
||||
# --- This logic now correctly targets a specific coin ---
|
||||
current_position = current_strategy_positions.get(coin)
|
||||
new_position_state = None # Return None to close position
|
||||
|
||||
if desired_signal == "BUY" or desired_signal == "INIT_BUY":
|
||||
new_position_state = {"coin": coin, "side": "long", "size": size}
|
||||
|
||||
if not current_position:
|
||||
logging.warning(f"[{name}]-[{coin}] ACTION: Setting leverage to {leverage_long}x and opening LONG.")
|
||||
self.send_order(agent_name, "update_leverage", coin, is_buy=True, size=leverage_long)
|
||||
self.send_order(agent_name, "market_open", coin, is_buy=True, size=size)
|
||||
self.log_trade(strategy=name, coin=coin, action="OPEN_LONG", price=signal_price, size=size, signal=desired_signal)
|
||||
|
||||
elif current_position['side'] == 'short':
|
||||
logging.warning(f"[{name}]-[{coin}] ACTION: Closing SHORT and opening LONG with {leverage_long}x leverage.")
|
||||
self.send_order(agent_name, "update_leverage", coin, is_buy=True, size=leverage_long)
|
||||
self.send_order(agent_name, "market_open", coin, is_buy=True, size=current_position['size'], reduce_only=True)
|
||||
self.log_trade(strategy=name, coin=coin, action="CLOSE_SHORT", price=signal_price, size=current_position['size'], signal=desired_signal)
|
||||
self.send_order(agent_name, "market_open", coin, is_buy=True, size=size)
|
||||
self.log_trade(strategy=name, coin=coin, action="OPEN_LONG", price=signal_price, size=size, signal=desired_signal)
|
||||
|
||||
else: # Already long, do nothing
|
||||
logging.info(f"[{name}]-[{coin}] INFO: Already LONG, no action taken.")
|
||||
new_position_state = current_position # State is unchanged
|
||||
|
||||
elif desired_signal == "SELL" or desired_signal == "INIT_SELL":
|
||||
new_position_state = {"coin": coin, "side": "short", "size": size}
|
||||
|
||||
if not current_position:
|
||||
logging.warning(f"[{name}]-[{coin}] ACTION: Setting leverage to {leverage_short}x and opening SHORT.")
|
||||
self.send_order(agent_name, "update_leverage", coin, is_buy=False, size=leverage_short)
|
||||
self.send_order(agent_name, "market_open", coin, is_buy=False, size=size)
|
||||
self.log_trade(strategy=name, coin=coin, action="OPEN_SHORT", price=signal_price, size=size, signal=desired_signal)
|
||||
|
||||
elif current_position['side'] == 'long':
|
||||
logging.warning(f"[{name}]-[{coin}] ACTION: Closing LONG and opening SHORT with {leverage_short}x leverage.")
|
||||
self.send_order(agent_name, "update_leverage", coin, is_buy=False, size=leverage_short)
|
||||
self.send_order(agent_name, "market_open", coin, is_buy=False, size=current_position['size'], reduce_only=True)
|
||||
self.log_trade(strategy=name, coin=coin, action="CLOSE_LONG", price=signal_price, size=current_position['size'], signal=desired_signal)
|
||||
self.send_order(agent_name, "market_open", coin, is_buy=False, size=size)
|
||||
self.log_trade(strategy=name, coin=coin, action="OPEN_SHORT", price=signal_price, size=size, signal=desired_signal)
|
||||
|
||||
else: # Already short, do nothing
|
||||
logging.info(f"[{name}]-[{coin}] INFO: Already SHORT, no action taken.")
|
||||
new_position_state = current_position # State is unchanged
|
||||
|
||||
elif desired_signal == "FLAT":
|
||||
if current_position:
|
||||
logging.warning(f"[{name}]-[{coin}] ACTION: Close {current_position['side']} position.")
|
||||
is_buy = current_position['side'] == 'short' # To close a short, we buy
|
||||
self.send_order(agent_name, "market_open", coin, is_buy=is_buy, size=current_position['size'], reduce_only=True)
|
||||
self.log_trade(strategy=name, coin=coin, action=f"CLOSE_{current_position['side'].upper()}", price=signal_price, size=current_position['size'], signal=desired_signal)
|
||||
# new_position_state is already None, which will remove it
|
||||
|
||||
return new_position_state
|
||||
Reference in New Issue
Block a user