446 lines
9.6 KiB
Markdown
446 lines
9.6 KiB
Markdown
# MetaTrader 5 Trading Skill for QwenClaw
|
|
|
|
## Overview
|
|
|
|
This skill enables QwenClaw to interact with MetaTrader 5 (MT5) for placing and managing trades on demo or live accounts.
|
|
|
|
**Integration:** Python MetaTrader5 package + MQL5
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
### 1. Install MetaTrader 5 Python Package
|
|
|
|
```bash
|
|
pip install MetaTrader5
|
|
```
|
|
|
|
### 2. Ensure MT5 Terminal is Running
|
|
|
|
The MT5 terminal must be logged in and running before executing trades.
|
|
|
|
### 3. Configure Account
|
|
|
|
- Demo account recommended for testing
|
|
- Ensure auto-trading is enabled (Alt+A)
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
### Place a Buy Order
|
|
|
|
```
|
|
Place a BUY order for EURUSD:
|
|
- Lot size: 0.1
|
|
- Stop Loss: 1.0800
|
|
- Take Profit: 1.0900
|
|
```
|
|
|
|
### Place a Sell Order
|
|
|
|
```
|
|
Place a SELL order for GBPUSD:
|
|
- Lot size: 0.05
|
|
- Stop Loss: 1.2700
|
|
- Take Profit: 1.2500
|
|
```
|
|
|
|
### Close All Positions
|
|
|
|
```
|
|
Close all open positions
|
|
```
|
|
|
|
### Get Account Info
|
|
|
|
```
|
|
Show my MT5 account balance and equity
|
|
```
|
|
|
|
### Get Open Positions
|
|
|
|
```
|
|
Show all open positions
|
|
```
|
|
|
|
---
|
|
|
|
## Python Implementation
|
|
|
|
```python
|
|
import MetaTrader5 as mt5
|
|
from datetime import datetime
|
|
|
|
class MT5Trader:
|
|
def __init__(self):
|
|
if not mt5.initialize():
|
|
raise Exception("Failed to initialize MT5 connection")
|
|
|
|
def get_account_info(self):
|
|
account_info = mt5.account_info()
|
|
return {
|
|
"balance": account_info.balance,
|
|
"equity": account_info.equity,
|
|
"margin": account_info.margin,
|
|
"profit": account_info.profit,
|
|
"currency": account_info.currency,
|
|
}
|
|
|
|
def get_positions(self):
|
|
positions = mt5.positions_get()
|
|
if positions is None:
|
|
return []
|
|
return [
|
|
{
|
|
"symbol": pos.symbol,
|
|
"type": "BUY" if pos.type == mt5.ORDER_TYPE_BUY else "SELL",
|
|
"volume": pos.volume,
|
|
"price_open": pos.price_open,
|
|
"price_current": pos.price_current,
|
|
"sl": pos.sl,
|
|
"tp": pos.tp,
|
|
"profit": pos.profit,
|
|
}
|
|
for pos in positions
|
|
]
|
|
|
|
def place_order(
|
|
self,
|
|
symbol: str,
|
|
order_type: str,
|
|
volume: float,
|
|
sl: float = None,
|
|
tp: float = None,
|
|
comment: str = "QwenClaw Trade"
|
|
):
|
|
# Get symbol info
|
|
symbol_info = mt5.symbol_info(symbol)
|
|
if symbol_info is None:
|
|
return {"success": False, "error": f"Symbol {symbol} not found"}
|
|
|
|
# Check if symbol is visible
|
|
if not symbol_info.visible:
|
|
if not mt5.symbol_select(symbol, True):
|
|
return {"success": False, "error": f"Failed to select symbol {symbol}"}
|
|
|
|
# Get current price
|
|
tick = mt5.symbol_info_tick(symbol)
|
|
if tick is None:
|
|
return {"success": False, "error": "Failed to get current price"}
|
|
|
|
# Determine order type and price
|
|
if order_type.upper() == "BUY":
|
|
trade_type = mt5.ORDER_TYPE_BUY
|
|
price = tick.ask
|
|
else:
|
|
trade_type = mt5.ORDER_TYPE_SELL
|
|
price = tick.bid
|
|
|
|
# Prepare order request
|
|
request = {
|
|
"action": mt5.TRADE_ACTION_DEAL,
|
|
"symbol": symbol,
|
|
"volume": volume,
|
|
"type": trade_type,
|
|
"price": price,
|
|
"sl": sl if sl else 0,
|
|
"tp": tp if tp else 0,
|
|
"deviation": 20,
|
|
"magic": 234000,
|
|
"comment": comment,
|
|
"type_time": mt5.ORDER_TIME_GTC,
|
|
"type_filling": mt5.ORDER_FILLING_IOC,
|
|
}
|
|
|
|
# Send order
|
|
result = mt5.order_send(request)
|
|
|
|
if result.retcode != mt5.TRADE_RETCODE_DONE:
|
|
return {
|
|
"success": False,
|
|
"error": f"Order failed: {result.comment}",
|
|
"retcode": result.retcode,
|
|
}
|
|
|
|
return {
|
|
"success": True,
|
|
"order": result.order,
|
|
"deal": result.deal,
|
|
"volume": result.volume,
|
|
"price": result.price,
|
|
"comment": result.comment,
|
|
}
|
|
|
|
def close_position(self, ticket: int):
|
|
position = mt5.positions_get(ticket=ticket)
|
|
if not position:
|
|
return {"success": False, "error": f"Position {ticket} not found"}
|
|
|
|
pos = position[0]
|
|
|
|
# Prepare close request
|
|
if pos.type == mt5.ORDER_TYPE_BUY:
|
|
trade_type = mt5.ORDER_TYPE_SELL
|
|
price = mt5.symbol_info_tick(pos.symbol).bid
|
|
else:
|
|
trade_type = mt5.ORDER_TYPE_BUY
|
|
price = mt5.symbol_info_tick(pos.symbol).ask
|
|
|
|
request = {
|
|
"action": mt5.TRADE_ACTION_DEAL,
|
|
"symbol": pos.symbol,
|
|
"volume": pos.volume,
|
|
"type": trade_type,
|
|
"position": ticket,
|
|
"price": price,
|
|
"deviation": 20,
|
|
"magic": 234000,
|
|
"comment": "Close position",
|
|
"type_time": mt5.ORDER_TIME_GTC,
|
|
"type_filling": mt5.ORDER_FILLING_IOC,
|
|
}
|
|
|
|
result = mt5.order_send(request)
|
|
|
|
if result.retcode != mt5.TRADE_RETCODE_DONE:
|
|
return {
|
|
"success": False,
|
|
"error": f"Close failed: {result.comment}",
|
|
}
|
|
|
|
return {
|
|
"success": True,
|
|
"deal": result.deal,
|
|
"profit": result.profit,
|
|
}
|
|
|
|
def close_all_positions(self):
|
|
positions = mt5.positions_get()
|
|
if positions is None:
|
|
return {"success": True, "closed": 0}
|
|
|
|
closed = 0
|
|
for pos in positions:
|
|
result = self.close_position(pos.ticket)
|
|
if result["success"]:
|
|
closed += 1
|
|
|
|
return {"success": True, "closed": closed}
|
|
|
|
def disconnect(self):
|
|
mt5.shutdown()
|
|
|
|
|
|
# Example usage
|
|
if __name__ == "__main__":
|
|
trader = MT5Trader()
|
|
|
|
# Get account info
|
|
info = trader.get_account_info()
|
|
print(f"Balance: {info['balance']} {info['currency']}")
|
|
print(f"Equity: {info['equity']}")
|
|
|
|
# Place a demo trade
|
|
result = trader.place_order(
|
|
symbol="EURUSD",
|
|
order_type="BUY",
|
|
volume=0.1,
|
|
sl=1.0800,
|
|
tp=1.0900
|
|
)
|
|
|
|
if result["success"]:
|
|
print(f"Order placed: {result['order']} at {result['price']}")
|
|
else:
|
|
print(f"Order failed: {result['error']}")
|
|
|
|
trader.disconnect()
|
|
```
|
|
|
|
---
|
|
|
|
## QwenClaw Integration
|
|
|
|
### Rig Agent Setup
|
|
|
|
```typescript
|
|
import { RigClient } from "./rig";
|
|
|
|
const rig = new RigClient({ host: "127.0.0.1", port: 8080 });
|
|
|
|
// Create trading agent
|
|
const traderAgentId = await rig.createAgent({
|
|
name: "mt5-trader",
|
|
preamble: `You are a MetaTrader 5 trading assistant.
|
|
|
|
When placing trades:
|
|
1. Always confirm symbol, direction, lot size
|
|
2. Set appropriate stop loss and take profit
|
|
3. Use demo account for testing
|
|
4. Report trade results clearly`,
|
|
provider: "qwen",
|
|
model: "qwen-plus",
|
|
});
|
|
|
|
// Place trade
|
|
const result = await rig.executePrompt(traderAgentId, `
|
|
Place a BUY order for EURUSD with:
|
|
- Lot size: 0.1
|
|
- Stop Loss: 50 pips
|
|
- Take Profit: 100 pips
|
|
`);
|
|
```
|
|
|
|
---
|
|
|
|
## Trade Examples
|
|
|
|
### Example 1: Simple Buy Order
|
|
|
|
**Request:**
|
|
```
|
|
Buy 0.1 lot EURUSD at market
|
|
```
|
|
|
|
**Expected Result:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"order": 123456789,
|
|
"deal": 987654321,
|
|
"volume": 0.1,
|
|
"price": 1.0850,
|
|
"symbol": "EURUSD",
|
|
"type": "BUY"
|
|
}
|
|
```
|
|
|
|
### Example 2: Sell Order with SL/TP
|
|
|
|
**Request:**
|
|
```
|
|
Sell 0.05 lot GBPUSD
|
|
Stop Loss: 1.2700
|
|
Take Profit: 1.2500
|
|
```
|
|
|
|
**Expected Result:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"order": 123456790,
|
|
"volume": 0.05,
|
|
"price": 1.2600,
|
|
"sl": 1.2700,
|
|
"tp": 1.2500,
|
|
"symbol": "GBPUSD",
|
|
"type": "SELL"
|
|
}
|
|
```
|
|
|
|
### Example 3: Close All Positions
|
|
|
|
**Request:**
|
|
```
|
|
Close all open positions
|
|
```
|
|
|
|
**Expected Result:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"closed": 3
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Risk Management
|
|
|
|
### Position Sizing
|
|
|
|
| Account Balance | Recommended Max Lot |
|
|
|-----------------|---------------------|
|
|
| $1,000 | 0.01 - 0.05 |
|
|
| $5,000 | 0.05 - 0.10 |
|
|
| $10,000 | 0.10 - 0.25 |
|
|
| $50,000+ | 0.25 - 0.50 |
|
|
|
|
### Stop Loss Guidelines
|
|
|
|
- **EURUSD/GBPUSD:** 20-50 pips typical
|
|
- **Gold (XAUUSD):** 50-100 pips typical
|
|
- **Indices:** 100-200 points typical
|
|
|
|
### Risk Per Trade
|
|
|
|
- **Conservative:** 1-2% of account per trade
|
|
- **Moderate:** 2-3% of account per trade
|
|
- **Aggressive:** 3-5% of account per trade (not recommended)
|
|
|
|
---
|
|
|
|
## Error Codes
|
|
|
|
| Retcode | Description |
|
|
|---------|-------------|
|
|
| 10006 | No connection |
|
|
| 10013 | Invalid request |
|
|
| 10014 | Invalid volume |
|
|
| 10015 | Invalid price |
|
|
| 10016 | Invalid stops |
|
|
| 10019 | Insufficient funds |
|
|
| 10023 | Request rejected |
|
|
| 10032 | Market closed |
|
|
|
|
---
|
|
|
|
## Safety Features
|
|
|
|
### Demo Mode (Default)
|
|
- Always use demo account first
|
|
- Verify account type before trading
|
|
|
|
### Confirmation Required
|
|
- Always confirm trade details before execution
|
|
- Show symbol, direction, volume, SL, TP
|
|
|
|
### Logging
|
|
- Log all trade requests
|
|
- Log all trade results
|
|
- Keep audit trail
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
- **MetaTrader 5 Python Docs:** https://www.mql5.com/en/docs/python
|
|
- **MetaTrader 5 Download:** https://www.metatrader5.com/en/download
|
|
- **MQL5 Community:** https://www.mql5.com/
|
|
|
|
---
|
|
|
|
## Skill Metadata
|
|
|
|
```yaml
|
|
name: metatrader5-trading
|
|
version: 1.0.0
|
|
category: trading
|
|
description: MetaTrader 5 trading integration for placing and managing forex/CFD trades
|
|
author: QwenClaw Team
|
|
license: MIT
|
|
tags:
|
|
- trading
|
|
- metatrader
|
|
- mt5
|
|
- forex
|
|
- cfd
|
|
- demo
|
|
```
|
|
|
|
---
|
|
|
|
**Skill ready for QwenClaw integration!** 📊💹
|