1515
1616Usage:
1717 Run with: ./test.sh (sets environment variables)
18- Or: uv run examples/async_06_multi_timeframe_strategy .py
18+ Or: uv run examples/06_multi_timeframe_strategy .py
1919
2020Author: TexasCoding
2121Date: July 2025
3131 create_trading_suite ,
3232)
3333from project_x_py .indicators import RSI , SMA
34+ from project_x_py .models import BracketOrderResponse , Position
3435
3536
36- class AsyncMultiTimeframeStrategy :
37+ class MultiTimeframeStrategy :
3738 """
3839 Async multi-timeframe trend following strategy.
3940
@@ -47,11 +48,13 @@ class AsyncMultiTimeframeStrategy:
4748
4849 def __init__ (
4950 self ,
51+ client : ProjectX ,
5052 trading_suite : dict ,
5153 symbol : str = "MNQ" ,
5254 max_position_size : int = 2 ,
5355 risk_percentage : float = 0.02 ,
5456 ):
57+ self .client = client
5558 self .suite = trading_suite
5659 self .symbol = symbol
5760 self .max_position_size = max_position_size
@@ -245,19 +248,20 @@ async def generate_trading_signal(self):
245248 async def execute_signal (self , signal_data : dict ):
246249 """Execute trading signal with proper risk management."""
247250 # Check current position
248- positions = await self .position_manager .get_all_positions ()
249- current_position = positions .get (self .symbol )
251+ positions : list [Position ] = await self .position_manager .get_all_positions ()
252+ current_position = next (
253+ (pos for pos in positions if pos .contractId == self .symbol ), None
254+ )
250255
251256 # Position size limits
252- if (
253- current_position
254- and abs (current_position .quantity ) >= self .max_position_size
255- ):
257+ if current_position and abs (current_position .size ) >= self .max_position_size :
256258 self .logger .info ("Max position size reached, skipping signal" )
257259 return
258260
259261 # Get account info for position sizing
260- account_balance = float (self .order_manager .project_x .account_info .balance )
262+ account_balance = (
263+ float (self .client .account_info .balance ) if self .client .account_info else 0
264+ )
261265
262266 # Calculate position size based on risk
263267 entry_price = signal_data ["price" ]
@@ -285,11 +289,11 @@ async def execute_signal(self, signal_data: dict):
285289 return
286290
287291 # Get active contract
288- instruments = await self .order_manager . project_x .search_instruments (self .symbol )
292+ instruments = await self .client .search_instruments (self .symbol )
289293 if not instruments :
290294 return
291295
292- contract_id = instruments [0 ].activeContract
296+ contract_id = instruments [0 ].id
293297
294298 # Place bracket order
295299 self .logger .info (
@@ -313,8 +317,14 @@ async def execute_signal(self, signal_data: dict):
313317 take_profit_price = take_profit ,
314318 )
315319
320+ if not isinstance (response , BracketOrderResponse ):
321+ self .logger .error (f"❌ Unexpected order type: { type (response )} " )
322+ return
323+
316324 if response and response .success :
317- self .logger .info (f"✅ Order placed successfully: { response .orderId } " )
325+ self .logger .info (
326+ f"✅ Order placed successfully: { response .entry_order_id } "
327+ )
318328 else :
319329 self .logger .error ("❌ Order placement failed" )
320330
@@ -433,7 +443,8 @@ def signal_handler(signum, frame):
433443 await suite ["data_manager" ].start_realtime_feed ()
434444
435445 # Create and configure strategy
436- strategy = AsyncMultiTimeframeStrategy (
446+ strategy = MultiTimeframeStrategy (
447+ client = client ,
437448 trading_suite = suite ,
438449 symbol = "MNQ" ,
439450 max_position_size = 2 ,
0 commit comments