Add position scaling feature via Telegram

- New endpoint: /api/trading/scale-position to add to existing positions
- Calculates new average entry price after adding more size
- Cancels old TP/SL orders and places new ones at updated levels
- Telegram command: /scale [percent] (default 50%)
- Example: /scale 100 doubles your position
- Automatically adjusts Position Manager tracking with new values
- Cleaned up stale duplicate trade from database
This commit is contained in:
mindesbunister
2025-10-27 20:24:06 +01:00
parent 6a04d3469f
commit 1acb5e7210
2 changed files with 318 additions and 0 deletions

View File

@@ -99,6 +99,98 @@ async def status_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
print(f"❌ Error: {e}", flush=True)
await update.message.reply_text(f"❌ Error: {str(e)}")
async def scale_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Handle /scale command - add to existing position and adjust TP/SL"""
# Only process from YOUR chat
if update.message.chat_id != ALLOWED_CHAT_ID:
await update.message.reply_text("❌ Unauthorized")
return
print(f"📈 /scale command received", flush=True)
try:
# First, get the current open position
pos_response = requests.get(
f"{TRADING_BOT_URL}/api/trading/positions",
headers={'Authorization': f'Bearer {API_SECRET_KEY}'},
timeout=10
)
if not pos_response.ok:
await update.message.reply_text(f"❌ Error fetching positions: {pos_response.status_code}")
return
pos_data = pos_response.json()
positions = pos_data.get('positions', [])
if not positions:
await update.message.reply_text("❌ No open positions to scale")
return
if len(positions) > 1:
await update.message.reply_text("❌ Multiple positions open. Please close extras first.")
return
position = positions[0]
trade_id = position['id']
# Determine scale percent from command argument
scale_percent = 50 # Default
if context.args and len(context.args) > 0:
try:
scale_percent = int(context.args[0])
if scale_percent < 10 or scale_percent > 200:
await update.message.reply_text("❌ Scale percent must be between 10 and 200")
return
except ValueError:
await update.message.reply_text("❌ Invalid scale percent. Usage: /scale [percent]")
return
# Send scaling request
response = requests.post(
f"{TRADING_BOT_URL}/api/trading/scale-position",
headers={'Authorization': f'Bearer {API_SECRET_KEY}'},
json={'tradeId': trade_id, 'scalePercent': scale_percent},
timeout=30
)
print(f"📥 API Response: {response.status_code}", flush=True)
if not response.ok:
data = response.json()
await update.message.reply_text(f"❌ Error: {data.get('message', 'Unknown error')}")
return
data = response.json()
if not data.get('success'):
await update.message.reply_text(f"{data.get('message', 'Failed to scale position')}")
return
# Build success message
message = f"✅ *Position Scaled by {scale_percent}%*\n\n"
message += f"*{position['symbol']} {position['direction'].upper()}*\n\n"
message += f"*Entry Price:*\n"
message += f" Old: ${data['oldEntry']:.2f}\n"
message += f" New: ${data['newEntry']:.2f}\n\n"
message += f"*Position Size:*\n"
message += f" Old: ${data['oldSize']:.0f}\n"
message += f" New: ${data['newSize']:.0f}\n\n"
message += f"*New Targets:*\n"
message += f" TP1: ${data['newTP1']:.2f}\n"
message += f" TP2: ${data['newTP2']:.2f}\n"
message += f" SL: ${data['newSL']:.2f}\n\n"
message += f"🎯 All TP/SL orders updated!"
await update.message.reply_text(message, parse_mode='Markdown')
print(f"✅ Position scaled: {scale_percent}%", flush=True)
except Exception as e:
print(f"❌ Error: {e}", flush=True)
await update.message.reply_text(f"❌ Error: {str(e)}")
async def validate_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Handle /validate command - check if positions match settings"""
@@ -238,6 +330,7 @@ def main():
print(f"\n✅ Commands:", flush=True)
print(f" /status - Show open positions", flush=True)
print(f" /validate - Validate positions against settings", flush=True)
print(f" /scale [percent] - Scale position (default 50%)", flush=True)
print(f" /buySOL, /sellSOL", flush=True)
print(f" /buyBTC, /sellBTC", flush=True)
print(f" /buyETH, /sellETH", flush=True)
@@ -248,6 +341,7 @@ def main():
# Add command handlers
application.add_handler(CommandHandler("status", status_command))
application.add_handler(CommandHandler("validate", validate_command))
application.add_handler(CommandHandler("scale", scale_command))
application.add_handler(CommandHandler("buySOL", trade_command))
application.add_handler(CommandHandler("sellSOL", trade_command))
application.add_handler(CommandHandler("buyBTC", trade_command))