"""Core: Strategy orchestration and signal generation.""" from loguru import logger class StrategyEngine: """Hosts and executes trading strategies, generating signals from market data.""" def __init__(self, order_manager): """ Initializes the StrategyEngine. Args: order_manager: The OrderManager instance to send signals to. """ self.order_manager = order_manager self.strategy = None self.last_price = None # For our simple demo strategy def load_strategy(self, strategy_name: str): """ Loads a trading strategy. For now, we use a simple hardcoded one. In the future, this will dynamically load strategy modules. """ if strategy_name == "simple_crossover": self.strategy = self._simple_crossover_strategy logger.info(f"Loaded strategy: {strategy_name}") else: logger.error(f"Strategy '{strategy_name}' not found.") async def on_tick(self, tick: dict): """ Called by the DataFeed on every new market data tick. Executes the loaded strategy. Args: tick (dict): The tick data from the data feed. """ if not self.strategy: return # The tick format from FYERS WebSocket is a list of dicts # For simplicity, we assume we get one instrument's data at a time if isinstance(tick, list) and tick: tick = tick[0] ltp = tick.get("ltp") symbol = tick.get("symbol") if ltp and symbol: await self.strategy(symbol, ltp) async def _simple_crossover_strategy(self, symbol: str, current_price: float): """ A very basic placeholder strategy. - If price goes up, BUY. - If price goes down, SELL. - Acts only on the first price change. This is for demonstration and is NOT a profitable strategy. """ if self.last_price is None: self.last_price = current_price logger.info(f"Starting price for {symbol} is {current_price}. Waiting for change.") return # Only trade once for this demo if abs(self.last_price - current_price) > 0.1: # Threshold to act if current_price > self.last_price: logger.warning(f"Price increased: {self.last_price} -> {current_price}. Sending BUY signal.") await self.order_manager.place_order( symbol=symbol, side="BUY", current_price=current_price, quantity=1, order_type="MARKET" ) elif current_price < self.last_price: logger.warning(f"Price decreased: {self.last_price} -> {current_price}. Sending SELL signal.") await self.order_manager.place_order( symbol=symbol, side="SELL", current_price=current_price, quantity=1, order_type="MARKET" ) # Stop further trading in this simple example self.strategy = None logger.info("Demo trade placed. Strategy deactivated.")