# 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!** 📊💹
