''' Supply & Demand Zone Trading Strategy Overview: Zone Identification: - Calculates supply zones (resistance areas where selling pressure exists) - Calculates demand zones (support areas where buying pressure exists) - Uses historical price action analysis to identify key levels - Zones represent areas where institutional orders likely cluster Entry Strategy: - BUY: Places orders at demand zone levels (support areas) - SELL: Places orders at supply zone levels (resistance areas) - Chooses the zone closest to current price for higher probability fills - Uses average of multiple zone levels for more reliable entries Position Management: - Supports partial position building (adds to positions under target size) - Maximum 1 full position at a time with partial fills allowed - Automatic position sizing adjustments based on existing exposure - Leverage: 3x (adjustable) Risk Management: - Profit target: 5% gain - Stop loss: 10% loss - Continuous PnL monitoring for existing positions - Order cancellation and replacement system Technical Setup: - Symbol: WIF (configurable) - Timeframe: 15 minutes for zone calculation - SMA confirmation: 20-period moving average - Lookback: 1 day for zone identification - Platform: Hyper Liquid (on-chain execution) Zone Logic: - Supply zones: Areas where price previously dropped (selling pressure) - Demand zones: Areas where price previously bounced (buying pressure) - Strategy assumes these levels will act as support/resistance again WARNING: Do not run without thorough backtesting and understanding! ''' import Functions.funcs as func import eth_account import time import pandas as pd import schedule import os from dotenv import load_dotenv load_dotenv() # Configuration symbol = 'WIF' timeframe = '15m' sma_window = 20 lookback_days = 1 size = 1 target = 5 max_loss = -10 leverage = 3 max_positions = 1 def get_account(): """Initialize trading account from private key""" secret = os.getenv('PRIVATE_KEY') return eth_account.Account.from_key(secret) def setup_account(): """Setup account with leverage""" account = get_account() func.adjust_leverage_size_signal(symbol, leverage, account) return account def get_position_info(symbol, account): """Get current position information and calculate adjusted size""" try: positions, in_position, position_size, pos_symbol, entry_price, pnl_percent, is_long = func.get_position(symbol, account) print(f'Position Status - In position: {in_position} | Size: {position_size} | PnL: {pnl_percent}%') # Calculate adjusted position size for partial fills if 0 < position_size < size: adjusted_size = size - position_size print(f'Partial position detected - Current: {position_size} | Needed: {adjusted_size}') return False, adjusted_size, positions # Treat as not in position for adding else: return in_position, size, positions except Exception as e: print(f'Error getting position info: {e}') return False, size, [] def get_supply_demand_zones(symbol): """Calculate supply and demand zones and determine best entry""" try: # Get supply and demand zones sd_df = func.supply_demand_zones_hl(symbol, timeframe, lookback_days) print('Supply & Demand Zones:') print(sd_df) # Convert to numeric sd_df[f'{timeframe}_dz'] = pd.to_numeric(sd_df[f'{timeframe}_dz'], errors='coerce') sd_df[f'{timeframe}_sz'] = pd.to_numeric(sd_df[f'{timeframe}_sz'], errors='coerce') # Calculate average zone levels demand_zone_avg = float(sd_df[f'{timeframe}_dz'].mean()) supply_zone_avg = float(sd_df[f'{timeframe}_sz'].mean()) # Get current price and SMA confirmation current_price = func.ask_bid(symbol)[0] latest_sma = func.get_latest_sma(symbol, timeframe, sma_window, 2) print(f'Market Data - Price: {current_price:.4f} | SMA: {latest_sma:.4f}') print(f'Zones - Demand: {demand_zone_avg:.4f} | Supply: {supply_zone_avg:.4f}') # Calculate distance to each zone distance_to_demand = abs(current_price - demand_zone_avg) distance_to_supply = abs(current_price - supply_zone_avg) print(f'Distances - To Demand: {distance_to_demand:.4f} | To Supply: {distance_to_supply:.4f}') # Choose closest zone for entry if distance_to_demand < distance_to_supply: return 'BUY', demand_zone_avg, 'demand' else: return 'SELL', supply_zone_avg, 'supply' except Exception as e: print(f'Error calculating supply/demand zones: {e}') return None, None, None def place_zone_trade(signal, entry_price, zone_type, position_size, account): """Place trade order at supply or demand zone""" try: func.cancel_all_orders(account) print('Canceled all existing orders') if signal == 'BUY': func.limit_order(symbol, True, position_size, entry_price, False, account) print(f'LONG order placed at {zone_type} zone: {position_size} at {entry_price:.4f}') elif signal == 'SELL': func.limit_order(symbol, False, position_size, entry_price, False, account) print(f'SHORT order placed at {zone_type} zone: {position_size} at {entry_price:.4f}') except Exception as e: print(f'Error placing zone trade: {e}') def bot(): try: print(f'\n---- Supply & Demand Zone Strategy for {symbol} ----') # Setup account account = get_account() # Get position information in_position, position_size, positions = get_position_info(symbol, account) # Check PnL for existing positions if in_position: print('Managing existing position') func.pnl_close(symbol, target, max_loss, account) return # Look for new trade opportunities print('Analyzing supply & demand zones...') signal, entry_price, zone_type = get_supply_demand_zones(symbol) if signal and entry_price: place_zone_trade(signal, entry_price, zone_type, position_size, account) else: print('No valid zone signals found') print('=' * 60) except Exception as e: print(f'Bot error: {e}') # Initial setup account = setup_account() schedule.every(30).seconds.do(bot) while True: try: schedule.run_pending() time.sleep(10) except Exception as e: print(f'Schedule error: {e} - Sleeping 30 seconds') time.sleep(30)