1
Fork 0
crypto_bot_training/Session_05/bots/HyperLiquid/Supply_Demand_Zone.py
2025-06-26 15:46:49 +02:00

191 lines
No EOL
6.6 KiB
Python

'''
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)