¿Por Qué Trading Algorítmico?
El trading algorítmico transforma la forma en que los traders interactúan con los mercados, ofreciendo precisión y eficiencia que el trading manual no puede igualar. Al automatizar tus estrategias, eliminas la toma de decisiones emocionales y aseguras una ejecución consistente en todas las condiciones del mercado.
Opera 24/7
Ejecuta tus estrategias las 24 horas sin que las decisiones emocionales afecten tus operaciones. Tu bot nunca duerme, nunca duda y nunca se desvía del plan.
Gestión de Riesgo Consistente
Aplica automáticamente parámetros de riesgo predefinidos incluyendo stop-losses, take-profits y dimensionamiento de posiciones. Asegura una gestión de riesgo consistente en todas las operaciones sin intervención manual.
Escala con Precisión
Ejecuta operaciones con timing perfecto y consistencia en múltiples instrumentos. Escala tu trading sin aumentar proporcionalmente tu compromiso de tiempo.
Captura Oportunidades
Aprovecha las oportunidades del mercado automáticamente conforme surgen en tiempo real. Reacciona a los movimientos de precio más rápido que cualquier trader manual.
Comenzando: Obtén Tu Clave API
Antes de poder ejecutar tu primer bot de trading, necesitas generar credenciales API desde tu cuenta SimpleFX. Sigue estos pasos para configurar tu acceso API:
Visita SimpleFX
Navega a simplefx.com e inicia sesión en tu cuenta
Accede a Configuración
Haz clic en el menú (icono hamburguesa) y selecciona Configuración
Sección API
Selecciona API del menú de configuración
Crear Clave API
Haz clic en el botón "Crear Clave API"
Configura Permisos
Nombra tu clave, selecciona permisos de trading y opcionalmente añade lista blanca de IPs para mayor seguridad
Genera y Guarda
Haz clic en Crear y copia inmediatamente tu secreto API (¡se muestra solo una vez!)
Confirma la Clave
Verifica mediante 2FA o enlace de confirmación por email
Copia el ID de la Clave
Guarda tu ID de Clave API del administrador para usarlo en tu código
¿Listo para empezar?
Abre tu cuenta SimpleFX ahora y genera tus credenciales API para comenzar el trading automatizado.
Abrir Cuenta GratisEjemplos de Estrategias de Trading
Aquí hay dos estrategias de ejemplo para ayudarte a comenzar con el trading algorítmico en SimpleFX. Cada enfoque tiene sus propias características y casos de uso.
Cruce de Medias Móviles Estático
Una estrategia basada en tiempo que analiza velas diarias, ejecuta operaciones basadas en el cruce SMA 10/50, y cierra posiciones automáticamente. Este enfoque funciona bien para traders que prefieren análisis programado sobre monitoreo continuo.
Características
- Analiza datos históricos de velas
- Usa Media Móvil Simple (SMA 10 vs SMA 50)
- Ejecución automática de operaciones (COMPRA/VENTA)
- Take Profit y Stop Loss integrados
- Funcionalidad de cierre automático por tiempo
- Usa solo REST API (no requiere conexión persistente)
Cómo Funciona
- Obtiene 60 velas diarias para análisis
- Calcula SMAs de 10 y 50 períodos
- Señal COMPRA: Cuando SMA10 > SMA50 (cruce alcista)
- Señal VENTA: Cuando SMA10 < SMA50 (cruce bajista)
- Establece TP/SL basado en distancia de precio definida
- Cierra automáticamente después del período establecido
import json
import requests
import time
import threading
from datetime import datetime, timedelta
class SimpleFXBot:
def __init__(self, client_id, client_secret, symbol="ETHUSD", amount=0.01, account_login=None, tp_distance=None, sl_distance=None):
self.client_id = client_id
self.client_secret = client_secret
self.symbol = symbol
self.amount = amount
self.base_url = "https://rest.simplefx.com"
self.candles_url = "https://candles-core.simplefx.com"
self.token = None
self.account_login = account_login
self.account_reality = "DEMO"
self.account_currency = "USD"
self.accounts = []
self.close_completed = False
self.tp_distance = tp_distance
self.sl_distance = sl_distance
self.symbol_digits = None
def authenticate(self):
"""Authenticate and get token"""
url = f"{self.base_url}/api/v3/auth/key"
payload = {"clientId": self.client_id, "clientSecret": self.client_secret}
headers = {"Content-Type": "application/json", "Accept": "application/json"}
print(f"Authenticating...")
try:
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
self.token = response.json()['data']['token']
print(f"✓ Authentication successful!")
return True
else:
print(f"✗ Authentication failed: {response.status_code}")
return False
except Exception as e:
print(f"✗ Error: {e}")
return False
def get_symbol_digits(self):
"""Get symbol digits from SimpleFX instruments JSON"""
print(f"\nFetching symbol information for {self.symbol}...")
try:
url = "https://simplefx.com/utils/instruments.json"
response = requests.get(url, timeout=10)
if response.status_code == 200:
instruments_dict = response.json()
for key, instrument_data in instruments_dict.items():
if not isinstance(instrument_data, dict):
continue
if instrument_data.get('symbol') == self.symbol:
self.symbol_digits = instrument_data.get('digits', 2)
print(f"✓ Found {self.symbol}: digits = {self.symbol_digits}")
return self.symbol_digits
print(f"⚠ Symbol {self.symbol} not found, using default digits = 2")
self.symbol_digits = 2
return self.symbol_digits
else:
print(f"✗ Failed to fetch instruments: {response.status_code}")
self.symbol_digits = 2
return self.symbol_digits
except Exception as e:
print(f"✗ Error fetching symbol digits: {e}")
self.symbol_digits = 2
return self.symbol_digits
def round_price(self, price):
"""Round price to symbol's digits"""
if self.symbol_digits is None:
return price
try:
return round(float(price), self.symbol_digits)
except (ValueError, TypeError):
return price
def get_headers(self):
return {
"Authorization": f"Bearer {self.token}",
"Content-Type": "application/json",
"Accept": "application/json"
}
def get_accounts(self):
"""Get account information"""
url = f"{self.base_url}/api/v3/accounts"
print(f"\nFetching accounts...")
try:
response = requests.get(url, headers=self.get_headers())
if response.status_code == 200:
self.accounts = response.json()['data']
print(f"✓ Found {len(self.accounts)} account(s)")
if not self.account_login:
for account in self.accounts:
if account['balance'] > 0:
self.account_login = account['login']
self.account_reality = account['reality']
self.account_currency = account['currency']
print(f" ➜ Auto-selected account: {self.account_login}")
break
else:
for account in self.accounts:
if account['login'] == self.account_login:
self.account_reality = account['reality']
self.account_currency = account['currency']
break
return self.accounts
else:
print(f"✗ Failed: {response.status_code}")
return None
except Exception as e:
print(f"✗ Error: {e}")
return None
def get_candles(self, num_candles=60):
"""Get daily candles for moving average calculation"""
print(f"\nFetching {num_candles} daily candles for {self.symbol}...")
try:
url = f"{self.candles_url}/api/v3/candles"
now = datetime.utcnow()
time_to = int(now.timestamp())
time_from = time_to - ((num_candles + 10) * 24 * 60 * 60)
params = {
"symbol": self.symbol,
"cPeriod": 86400,
"timeFrom": time_from,
"timeTo": time_to
}
response = requests.get(url, params=params, headers=self.get_headers(), timeout=10)
if response.status_code == 200:
data = response.json()
if 'data' in data and len(data['data']) > 0:
candles = data['data']
print(f" ✓ Received {len(candles)} candle(s)")
return candles
else:
print(f"✗ No candle data returned")
return None
else:
print(f"✗ HTTP error: {response.status_code}")
return None
except Exception as e:
print(f"✗ Error fetching candle data: {e}")
return None
def calculate_sma(self, candles, period):
"""Calculate Simple Moving Average"""
if len(candles) < period:
return None
recent_candles = candles[-period:]
close_prices = [candle['close'] for candle in recent_candles]
return sum(close_prices) / len(close_prices)
def analyze_moving_averages(self):
"""Analyze moving averages and determine trade direction"""
print(f"\n{'='*50}")
print("MOVING AVERAGE ANALYSIS")
print("="*50)
candles = self.get_candles(num_candles=60)
if not candles or len(candles) < 50:
print(f"✗ Not enough candle data for analysis")
return None, None
print(f"\nCalculating Moving Averages...")
sma_10 = self.calculate_sma(candles, 10)
sma_50 = self.calculate_sma(candles, 50)
if sma_10 is None or sma_50 is None:
return None, None
current_price = candles[-1]['close']
print(f" Current Price: ${current_price:,.2f}")
print(f" SMA 10 (Fast): ${sma_10:,.2f}")
print(f" SMA 50 (Slow): ${sma_50:,.2f}")
if sma_10 > sma_50:
print(f"\n✓ BULLISH SIGNAL → Opening BUY position")
return "BUY", current_price
else:
print(f"\n✓ BEARISH SIGNAL → Opening SELL position")
return "SELL", current_price
def calculate_tp_sl_prices(self, side, current_price):
"""Calculate TP and SL prices based on distance"""
tp_price = None
sl_price = None
if self.tp_distance and self.tp_distance > 0:
if side.upper() == "BUY":
tp_price = current_price + self.tp_distance
else:
tp_price = current_price - self.tp_distance
tp_price = self.round_price(tp_price)
if self.sl_distance and self.sl_distance > 0:
if side.upper() == "BUY":
sl_price = current_price - self.sl_distance
else:
sl_price = current_price + self.sl_distance
sl_price = self.round_price(sl_price)
return tp_price, sl_price
def open_market_order(self, side="BUY", current_price=None):
"""Open a market order with TP and SL"""
url = f"{self.base_url}/api/v3/trading/orders/market"
order_data = {
"Reality": self.account_reality,
"Login": self.account_login,
"Symbol": self.symbol,
"Side": side.upper(),
"Volume": self.amount,
"IsFIFO": True
}
if current_price:
tp_price, sl_price = self.calculate_tp_sl_prices(side, current_price)
if tp_price:
order_data["TakeProfit"] = tp_price
if sl_price:
order_data["StopLoss"] = sl_price
print(f"\nOpening {side.upper()} Market Order...")
try:
response = requests.post(url, json=order_data, headers=self.get_headers())
if response.status_code in [200, 201]:
response_data = response.json()
print(f"✓ SUCCESS! Order placed")
market_orders = response_data.get('data', {}).get('marketOrders', [])
if market_orders:
order = market_orders[0].get('order', {})
return {
"id": order.get('id'),
"volume": order.get('volume'),
"side": order.get('side'),
"symbol": order.get('symbol')
}
return None
else:
print(f"✗ FAILED to place order: {response.status_code}")
return None
except Exception as e:
print(f"✗ ERROR: {e}")
return None
def close_order(self, order_info):
"""Close a market order"""
url = f"{self.base_url}/api/v3/trading/orders/market"
opposite_side = "SELL" if order_info['side'].upper() == "BUY" else "BUY"
close_data = {
"Reality": self.account_reality,
"Login": self.account_login,
"Symbol": order_info['symbol'],
"Side": opposite_side,
"Volume": order_info['volume'],
"CloseBy": order_info['id'],
"IsFIFO": True
}
print(f"\nClosing Order {order_info['id']}...")
try:
response = requests.post(url, json=close_data, headers=self.get_headers())
if response.status_code in [200, 201]:
print(f"✓ SUCCESS! Order closed")
self.close_completed = True
return True
else:
print(f"✗ FAILED to close order")
self.close_completed = True
return False
except Exception as e:
print(f"✗ ERROR: {e}")
self.close_completed = True
return False
def schedule_close_order(self, order_info, delay_seconds=60):
"""Schedule order closure after delay"""
def close_after_delay():
print(f"\n⏱ Order will close in {delay_seconds} seconds")
time.sleep(delay_seconds)
print(f"\n⏰ Time's up! Closing order now...")
self.close_order(order_info)
thread = threading.Thread(target=close_after_delay)
thread.daemon = False
thread.start()
return thread
def run_strategy(self):
"""Execute the moving average crossover strategy"""
print("\n" + "="*50)
print("SimpleFX Moving Average Crossover Bot")
print("="*50)
print(f"Symbol: {self.symbol}")
print(f"Amount: {self.amount} lots")
print(f"Strategy: SMA 10/50 Crossover")
# Step 1: Authenticate
if not self.authenticate():
return False
# Step 2: Get symbol digits
self.get_symbol_digits()
# Step 3: Get accounts
if not self.get_accounts() or not self.account_login:
return False
# Step 4: Analyze moving averages
trade_side, current_price = self.analyze_moving_averages()
if trade_side is None:
print("\n⚠ Could not analyze moving averages. Aborting.")
return False
# Step 5: Open trade
order_info = self.open_market_order(side=trade_side, current_price=current_price)
if order_info:
# Step 6: Schedule auto-close
close_thread = self.schedule_close_order(order_info, delay_seconds=60)
close_thread.join()
return True
else:
print("\n✗ Trade execution failed")
return False
def main():
print("SimpleFX Moving Average Crossover Bot")
print("="*50)
CLIENT_ID = input("Enter your Client ID: ").strip()
CLIENT_SECRET = input("Enter your Client Secret: ").strip()
if not CLIENT_ID or not CLIENT_SECRET:
print("\n⚠ ERROR: Client ID and Client Secret are required!")
return
SYMBOL = input("Enter Trading Symbol [default: BTCUSD]: ").strip().upper() or "BTCUSD"
VOLUME = float(input("Enter Trade Volume [default: 0.01]: ").strip() or "0.01")
tp_input = input("Take Profit distance in $ (or Enter to skip): ").strip()
tp_distance = float(tp_input) if tp_input else None
sl_input = input("Stop Loss distance in $ (or Enter to skip): ").strip()
sl_distance = float(sl_input) if sl_input else None
bot = SimpleFXBot(CLIENT_ID, CLIENT_SECRET, SYMBOL, VOLUME, None, tp_distance, sl_distance)
bot.run_strategy()
if __name__ == "__main__":
main()Bot de Trading por Umbral de Precio
Una estrategia basada en WebSocket que monitorea precios XAUUSD (Oro) en tiempo real y ejecuta automáticamente una orden de COMPRA cuando el precio cae por debajo de tu objetivo especificado. Perfecto para traders que quieren entrar en posiciones a niveles de precio específicos sin monitoreo manual constante.
Características
- Streaming de precios en tiempo real vía WebSocket
- Activación automática de COMPRA al precio objetivo
- Take Profit y Stop Loss configurables
- Enfocado en trading de XAUUSD (Oro)
- Manejo automático de reconexión
- Configuración interactiva vía CLI
Cómo Funciona
- Se autentica con SimpleFX API usando tus credenciales
- Se conecta vía WebSocket para cotizaciones XAUUSD en vivo
- Monitorea el precio Ask en tiempo real
- Activa COMPRA cuando el precio cae por debajo de tu objetivo
- Coloca orden de mercado con TP/SL configurado
- Cierra conexión después de ejecución exitosa
import asyncio
import websockets
import json
from datetime import datetime
import logging
import sys
import nest_asyncio
from websockets.exceptions import ConnectionClosed
import requests
# Apply nest_asyncio to allow nested event loops
nest_asyncio.apply()
# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class SimpleFXTrader:
def __init__(self, client_id, client_secret):
self.client_id = client_id
self.client_secret = client_secret
self.base_url = "https://rest.simplefx.com"
self.token = None
self.account_login = None
self.account_reality = "DEMO"
self.account_currency = "USD"
self.price_precision = None
def authenticate(self):
"""Authenticate and get token"""
url = f"{self.base_url}/api/v3/auth/key"
payload = {"clientId": self.client_id, "clientSecret": self.client_secret}
headers = {"Content-Type": "application/json", "Accept": "application/json"}
logger.info("Authenticating...")
try:
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
self.token = response.json()['data']['token']
logger.info("✓ Authentication successful!")
return True
else:
logger.error(f"✗ Authentication failed: {response.status_code}")
logger.error(f"Response: {response.text}")
return False
except Exception as e:
logger.error(f"✗ Error: {e}")
return False
def get_headers(self):
return {
"Authorization": f"Bearer {self.token}",
"Content-Type": "application/json",
"Accept": "application/json"
}
def get_accounts(self):
"""Get account information"""
url = f"{self.base_url}/api/v3/accounts"
logger.info("Fetching accounts...")
try:
response = requests.get(url, headers=self.get_headers())
if response.status_code == 200:
accounts = response.json()['data']
logger.info(f"✓ Found {len(accounts)} account(s)")
for i, account in enumerate(accounts, 1):
logger.info(f"\n [{i}] Login: {account['login']}")
logger.info(f" Currency: {account['currency']}")
logger.info(f" Balance: {account['balance']}")
logger.info(f" Type: {account['reality']}")
for account in accounts:
if account['balance'] > 0:
self.account_login = account['login']
self.account_reality = account['reality']
self.account_currency = account['currency']
logger.info(f"\n ➜ Selected account: {self.account_login} ({self.account_reality})")
logger.info(f" Balance: {account['balance']} {account['currency']}")
return True
logger.error("✗ No account with balance found")
return False
else:
logger.error(f"✗ Failed: {response.status_code}")
logger.error(f"Response: {response.text}")
return False
except Exception as e:
logger.error(f"✗ Error: {e}")
return False
def get_instrument_precision(self, symbol):
"""Get price precision for the symbol"""
logger.info(f"Fetching instrument precision for {symbol}...")
try:
url = "https://simplefx.com/utils/instruments.json"
response = requests.get(url, timeout=10)
if response.status_code == 200:
data = response.json()
if isinstance(data, dict):
for key, instrument in data.items():
if isinstance(instrument, dict):
if instrument.get('symbol') == symbol or key == symbol:
digits = instrument.get('digits')
if digits is not None:
self.price_precision = digits
logger.info(f" ✓ Precision: {digits} digits")
return digits
elif isinstance(data, list):
for instrument in data:
if isinstance(instrument, dict):
if instrument.get('symbol') == symbol:
digits = instrument.get('digits')
if digits is not None:
self.price_precision = digits
logger.info(f" ✓ Precision: {digits} digits")
return digits
logger.warning(f" ⚠ Symbol not found, using default: 2 digits")
self.price_precision = 2
return 2
else:
logger.warning(f" Using default precision: 2 digits")
self.price_precision = 2
return 2
except Exception as e:
logger.error(f" ✗ Error: {e}")
self.price_precision = 2
return 2
def round_price(self, price):
"""Round price to instrument's precision"""
if self.price_precision is None:
self.price_precision = 2
return round(price, self.price_precision)
def open_market_order(self, symbol, side, amount, tp_price=None, sl_price=None):
"""Open a market order"""
url = f"{self.base_url}/api/v3/trading/orders/market"
order_data = {
"Reality": self.account_reality,
"Login": self.account_login,
"Symbol": symbol,
"Side": side.upper(),
"Volume": amount,
"IsFIFO": True
}
if tp_price:
order_data["TakeProfit"] = tp_price
if sl_price:
order_data["StopLoss"] = sl_price
logger.info(f"\n{'='*60}")
logger.info(f"Placing {side.upper()} Market Order")
logger.info(f"{'='*60}")
logger.info(f" Symbol: {symbol}")
logger.info(f" Volume: {amount} lots")
logger.info(f" Account: {self.account_login} ({self.account_reality})")
if tp_price:
logger.info(f" Take Profit: ${tp_price:,.{self.price_precision}f}")
if sl_price:
logger.info(f" Stop Loss: ${sl_price:,.{self.price_precision}f}")
try:
response = requests.post(url, json=order_data, headers=self.get_headers(), timeout=10)
if response.status_code in [200, 201]:
response_data = response.json()
logger.info(f"\n✓ SUCCESS! Market order placed")
market_orders = response_data.get('data', {}).get('marketOrders', [])
if market_orders:
order = market_orders[0].get('order', {})
order_id = order.get('id')
open_price = order.get('openPrice')
logger.info(f"\n✓ Order Details:")
logger.info(f" Order ID: {order_id}")
logger.info(f" Symbol: {order.get('symbol')}")
logger.info(f" Side: {order.get('side')}")
logger.info(f" Volume: {order.get('volume')}")
if open_price:
logger.info(f" Open Price: ${open_price:,.{self.price_precision}f}")
return {
"id": order_id,
"open_price": open_price,
"volume": order.get('volume'),
"side": order.get('side'),
"symbol": order.get('symbol')
}
return response_data
else:
logger.error(f"\n✗ FAILED to place order")
logger.error(f"Status Code: {response.status_code}")
return None
except Exception as e:
logger.error(f"\n✗ ERROR: {e}")
return None
class GoldPriceMonitor:
def __init__(self, trader, target_price, amount=0.01, tp_distance=None, sl_distance=None):
self.trader = trader
self.target_price = target_price
self.amount = amount
self.tp_distance = tp_distance
self.sl_distance = sl_distance
self.symbol = "XAUUSD"
self.running = True
self.order_placed = False
self.ws = None
self.subscription_id = 0
self.last_log_time = None
self.trigger_ask = None
async def connect_and_monitor(self):
"""Connect to WebSocket and monitor XAUUSD prices"""
uri = "wss://web-quotes-core.simplefx.com/websocket/quotes"
logger.info(f"\n{'='*60}")
logger.info("Starting Price Monitor")
logger.info(f"{'='*60}")
logger.info(f" Symbol: {self.symbol}")
logger.info(f" Target Price: ${self.target_price:,.2f}")
logger.info(f" Action: Waiting for price to drop BELOW target")
logger.info(f" Trade Size: {self.amount} lots")
if self.tp_distance:
logger.info(f" Take Profit: ${self.tp_distance} above entry")
if self.sl_distance:
logger.info(f" Stop Loss: ${self.sl_distance} below entry")
logger.info(f"{'='*60}\n")
while self.running and not self.order_placed:
try:
async with websockets.connect(uri) as ws:
self.ws = ws
logger.info("✓ Connected to WebSocket")
# Subscribe to XAUUSD
self.subscription_id += 1
subscription_message = json.dumps({
"p": "/subscribe/addList",
"i": self.subscription_id,
"d": [self.symbol]
})
await ws.send(subscription_message)
logger.info(f"✓ Subscribed to {self.symbol} prices")
logger.info(f"\n⏳ Monitoring prices... (Press Ctrl+C to stop)\n")
# Start heartbeat
heartbeat_task = asyncio.create_task(self._send_heartbeat(ws))
try:
while self.running and not self.order_placed:
response = await ws.recv()
await self.process_quote(response)
except ConnectionClosed:
if not self.order_placed:
logger.warning("WebSocket closed, reconnecting...")
finally:
heartbeat_task.cancel()
except Exception as e:
if self.running and not self.order_placed:
logger.error(f"Connection error: {str(e)}")
logger.info("Reconnecting in 5 seconds...")
await asyncio.sleep(5)
else:
break
async def _send_heartbeat(self, ws):
"""Send periodic heartbeat"""
while self.running and not self.order_placed:
try:
await asyncio.sleep(30)
await ws.send(json.dumps({"type": "ping"}))
except Exception as e:
logger.error(f"Heartbeat error: {str(e)}")
break
async def process_quote(self, quote_data):
"""Process incoming quote and check if we should trade"""
try:
data = json.loads(quote_data)
if data.get("p") == "/quotes/subscribed":
quotes_data = data.get("d", [])
for quote in quotes_data:
symbol = quote.get("s")
if symbol == self.symbol:
bid = quote.get("b")
ask = quote.get("a")
if bid and ask:
current_time = datetime.now()
# Log every 2 seconds
if self.last_log_time is None or (current_time - self.last_log_time).total_seconds() >= 2:
time_str = current_time.strftime('%H:%M:%S')
logger.info(f"[{time_str}] {symbol} - Bid: ${bid:,.2f} | Ask: ${ask:,.2f} | Target: ${self.target_price:,.2f}")
self.last_log_time = current_time
# Check if ask price is below target
if ask <= self.target_price and not self.order_placed:
self.order_placed = True
self.trigger_ask = ask
logger.info(f"\n{'='*60}")
logger.info(f"🎯 TARGET REACHED!")
logger.info(f"{'='*60}")
logger.info(f" Current Ask: ${ask:,.2f}")
logger.info(f" Target Price: ${self.target_price:,.2f}")
logger.info(f"{'='*60}\n")
# Close WebSocket before placing order
self.running = False
if self.ws:
await self.ws.close()
await asyncio.sleep(1)
self.place_order_sync()
except json.JSONDecodeError as e:
logger.error(f"Error decoding JSON: {e}")
except Exception as e:
logger.error(f"Error processing quote: {str(e)}")
def place_order_sync(self):
"""Place order after WebSocket is closed"""
tp_price = None
sl_price = None
if self.tp_distance:
tp_price = self.trader.round_price(self.trigger_ask + self.tp_distance)
if self.sl_distance:
sl_price = self.trader.round_price(self.trigger_ask - self.sl_distance)
order = self.trader.open_market_order(
self.symbol,
"BUY",
self.amount,
tp_price,
sl_price
)
if order:
logger.info(f"\n✓✓✓ Order placed successfully!")
else:
logger.error(f"\n✗ Failed to place order")
def stop(self):
"""Stop monitoring"""
self.running = False
async def main():
print("""
╔══════════════════════════════════════════════════════════╗
║ XAUUSD Price Threshold Trading Bot ║
║ Automatically opens BUY when price drops below ║
║ your specified target price ║
╚══════════════════════════════════════════════════════════╝
""")
# Configuration
CLIENT_ID = input("\n🔑 Enter your SimpleFX Client ID: ").strip()
CLIENT_SECRET = input("🔑 Enter your SimpleFX Client Secret: ").strip()
if not CLIENT_ID or not CLIENT_SECRET:
print("\n✗ Error: Client ID and Secret are required")
return
# Get target price
while True:
try:
target_price_input = input("\n💰 Enter target price for XAUUSD: $").strip()
target_price = float(target_price_input)
if target_price > 0:
break
else:
print(" ✗ Please enter a positive number")
except ValueError:
print(" ✗ Invalid input. Please enter a valid price")
# Get trade size
while True:
try:
amount_input = input("\n📊 Enter trade size in lots (e.g., 0.01): ").strip() or "0.01"
amount = float(amount_input)
if amount > 0:
break
else:
print(" ✗ Please enter a positive number")
except ValueError:
print(" ✗ Invalid input")
# Get TP and SL
print(f"\n{'='*60}")
print("TAKE PROFIT & STOP LOSS (Optional)")
print("="*60)
tp_distance = None
sl_distance = None
tp_input = input("\n💰 Take Profit distance in $ (e.g., 10): $").strip()
if tp_input:
try:
tp_distance = float(tp_input)
if tp_distance > 0:
print(f" ➜ Take Profit set to ${tp_distance}")
else:
tp_distance = None
except ValueError:
print(" ✗ Invalid input, skipping Take Profit")
sl_input = input("\n🛡️ Stop Loss distance in $ (e.g., 5): $").strip()
if sl_input:
try:
sl_distance = float(sl_input)
if sl_distance > 0:
print(f" ➜ Stop Loss set to ${sl_distance}")
else:
sl_distance = None
except ValueError:
print(" ✗ Invalid input, skipping Stop Loss")
# Summary
print(f"\n{'='*60}")
print("CONFIGURATION SUMMARY")
print("="*60)
print(f" Symbol: XAUUSD (Gold)")
print(f" Target Price: ${target_price:,.2f}")
print(f" Trade Size: {amount} lots")
print(f" Action: BUY when Ask price ≤ ${target_price:,.2f}")
if tp_distance:
print(f" Take Profit: ${tp_distance} above entry")
if sl_distance:
print(f" Stop Loss: ${sl_distance} below entry")
print("="*60)
user_input = input(f"\n⚠ Start monitoring? (yes/no): ").strip().lower()
if user_input != 'yes':
print("\n👋 Cancelled.")
return
# Initialize trader
trader = SimpleFXTrader(CLIENT_ID, CLIENT_SECRET)
if not trader.authenticate():
print("\n✗ Authentication failed. Exiting.")
return
if not trader.get_accounts():
print("\n✗ Failed to get accounts. Exiting.")
return
trader.get_instrument_precision("XAUUSD")
# Start monitoring
monitor = GoldPriceMonitor(trader, target_price, amount, tp_distance, sl_distance)
try:
await monitor.connect_and_monitor()
if monitor.order_placed:
print(f"\n{'='*60}")
print("🎉 TRADE COMPLETED!")
print("="*60)
else:
print(f"\n⚠ Monitor stopped without placing order")
except KeyboardInterrupt:
print("\n\n⚠ Interrupted by user!")
monitor.stop()
print("👋 Goodbye!")
except Exception as e:
logger.error(f"\n✗ Unexpected error: {e}")
if __name__ == "__main__":
if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\n\n👋 Goodbye!")Consejo
Cuando uses LLMs (como ChatGPT, Claude o Copilot) para escribir código de trading, referencia la especificación OpenAPI en tus prompts para obtener resultados más precisos:
https://simplefx.com/docs/api/oas3-3.1.json¿Por Qué Operar con SimpleFX?
SimpleFX proporciona el entorno ideal para traders algorítmicos. Con una API robusta, ejecución rápida y acceso a más de 1,000 instrumentos, tienes todo lo que necesitas para construir y ejecutar estrategias de trading sofisticadas.
Beneficios de la Plataforma
- ✓Ejecución ultrarrápida con procesamiento de órdenes en menos de un segundo optimizado para trading algorítmico
- ✓Acceso a más de 1,000 instrumentos incluyendo criptomonedas, forex, índices, materias primas y CFDs de acciones
- ✓Acceso completo a REST API con soporte WebSocket para datos en tiempo real y documentación completa
- ✓Spreads competitivos con precios transparentes y sin comisiones ocultas
- ✓Plataforma web profesional y apps móviles con gráficos avanzados y herramientas de gestión de riesgo
- ✓Apertura de cuenta rápida sin depósito mínimo requerido y cuenta demo disponible
Ya sea que estés construyendo tu primer bot de trading o escalando una estrategia compleja multi-instrumento, SimpleFX proporciona las herramientas e infraestructura que necesitas para tener éxito.
Aviso Legal
Los ejemplos de código proporcionados en esta página son solo para fines educativos. Pueden contener errores o bugs y no están destinados para uso en producción sin pruebas y modificaciones exhaustivas. SimpleFX no es responsable de pérdidas comerciales, problemas técnicos u otros daños resultantes del uso de estos ejemplos de código. Siempre realiza pruebas exhaustivas en un entorno demo antes de usar cualquier estrategia de trading automatizada con fondos reales.