This commit is contained in:
blade 2025-07-21 13:05:59 +08:00
commit d1079d338d
9 changed files with 1110 additions and 0 deletions

42
.cursorrules Normal file
View File

@ -0,0 +1,42 @@
# Role
你是一名精通Python的高级工程师拥有20年的软件开发经验。你的任务是帮助一位不太懂技术的初中生用户完成Python项目的开发。你的工作对用户来说非常重要完成后将获得10000美元奖励。
# Goal
你的目标是以用户容易理解的方式帮助他们完成Python项目的设计和开发工作。你应该主动完成所有工作而不是等待用户多次推动你。
在理解用户需求、编写代码和解决问题时,你应始终遵循以下原则:
## 第一步:项目初始化
- 当用户提出任何需求时首先浏览项目根目录下的README.md文件和所有代码文档理解项目目标、架构和实现方式。
- 如果还没有README文件创建一个。这个文件将作为项目功能的说明书和你对项目内容的规划。
- 在README.md中清晰描述所有功能的用途、使用方法、参数说明和返回值说明确保用户可以轻松理解和使用这些功能。
## 第二步:需求分析和开发
### 理解用户需求时:
- 充分理解用户需求,站在用户角度思考。
- 作为产品经理,分析需求是否存在缺漏,与用户讨论并完善需求。
- 选择最简单的解决方案来满足用户需求。
### 编写代码时:
- 遵循PEP 8 Python代码风格指南。
- 使用最新的Python 3语法特性和最佳实践。
- 合理使用面向对象编程(OOP)和函数式编程范式。
- 利用Python的标准库和生态系统中的优质第三方库。
- 实现模块化设计,确保代码的可重用性和可维护性。
- 使用类型提示(Type Hints)进行类型检查,提高代码质量。
- 编写详细的文档字符串(docstring)和注释。
- 实现适当的错误处理和日志记录。
- 编写单元测试确保代码质量。
### 解决问题时:
- 全面阅读相关代码文件,理解所有代码的功能和逻辑。
- 分析导致错误的原因,提出解决问题的思路。
- 与用户进行多次交互,根据反馈调整解决方案。
## 第三步:项目总结和优化
- 完成任务后,反思完成步骤,思考项目可能存在的问题和改进方式。
- 更新README.md文件包括新增功能说明和优化建议。
- 考虑使用Python的高级特性如异步编程、并发处理等来优化性能。
- 优化代码性能,包括算法复杂度、内存使用和执行效率。
在整个过程中,始终参考[Python官方文档](https://docs.python.org/)确保使用最新的Python开发最佳实践。

94
QUICKSTART.md Normal file
View File

@ -0,0 +1,94 @@
# 快速开始指南
## 🚀 5分钟快速上手
### 第一步:安装依赖
```bash
pip install -r requirements.txt
```
### 第二步:运行演示版本
```bash
python demo.py
```
选择任意策略进行回测,体验量化交易逻辑。
### 第三步获取OKX API密钥可选
1. 注册 [OKX账户](https://www.okx.com/)
2. 进入"账户中心" → "API管理"
3. 创建API Key获取
- API Key
- Secret Key
- Passphrase
### 第四步配置API密钥
编辑 `config.py` 文件:
```python
API_KEY = "your_actual_api_key"
SECRET_KEY = "your_actual_secret_key"
PASSPHRASE = "your_actual_passphrase"
```
### 第五步:测试连接
```bash
python test_connection.py
```
### 第六步:运行实盘版本
```bash
python play.py
```
## 📊 策略说明
### 移动平均线策略 (SMA)
- **原理**: 短期均线上穿长期均线买入,下穿卖出
- **适用**: 趋势明显的市场
- **参数**: 短期5期长期20期
### RSI策略
- **原理**: RSI < 30 超卖买入RSI > 70 超买卖出
- **适用**: 震荡市场
- **参数**: 14期RSI超卖30超买70
### 网格交易策略
- **原理**: 在价格区间内设置网格,低买高卖
- **适用**: 横盘整理市场
- **参数**: 5个网格2%范围
## ⚠️ 重要提醒
1. **风险控制**: 加密货币交易存在高风险
2. **资金管理**: 不要投入超过承受能力的资金
3. **测试环境**: 建议先在沙盒环境测试
4. **策略优化**: 根据市场情况调整策略参数
## 🆘 常见问题
**Q: 演示版本和实盘版本有什么区别?**
A: 演示版本使用模拟数据,实盘版本连接真实交易所。
**Q: 如何调整交易数量?**
A: 修改 `config.py` 中的 `"position_size"` 参数。
**Q: 如何切换到实盘交易?**
A: 在 `config.py` 中将 `"sandbox": True` 改为 `"sandbox": False`
**Q: API调用失败怎么办**
A: 检查API密钥、网络连接和API权限。
## 📞 技术支持
如有问题,请检查:
1. 依赖包是否正确安装
2. API密钥是否正确配置
3. 网络连接是否正常
4. 交易所服务是否可用

164
README.md Normal file
View File

@ -0,0 +1,164 @@
# 比特币量化交易系统
这是一个基于OKX API的比特币量化交易系统支持多种交易策略。
## 功能特性
- 🔐 使用OKX官方Python SDK
- 📊 支持多种技术指标SMA、RSI等
- 🤖 三种量化交易策略
- 🛡️ 沙盒环境测试支持
- 📈 实时行情数据获取
- 💰 账户余额查询
- ⚙️ 可配置的交易参数
## 支持的策略
### 1. 移动平均线策略 (SMA)
- 使用短期和长期移动平均线
- 短期均线上穿长期均线时买入
- 短期均线下穿长期均线时卖出
### 2. RSI策略
- 基于相对强弱指数(RSI)
- RSI < 30 时买入超卖
- RSI > 70 时卖出(超买)
### 3. 网格交易策略
- 在价格区间内设置多个网格
- 价格下跌到网格线时买入
- 价格上涨到网格线时卖出
## 安装依赖
```bash
# 方法1使用requirements.txt
pip install -r requirements.txt
# 方法2手动安装
pip install okx pandas numpy
```
## 配置API密钥
1. 登录 [OKX官网](https://www.okx.com/)
2. 进入"账户中心" → "API管理"
3. 创建新的API Key获取以下信息
- API Key
- Secret Key
- Passphrase
4. 编辑 `config.py` 文件填入你的API密钥
```python
API_KEY = "your_actual_api_key"
SECRET_KEY = "your_actual_secret_key"
PASSPHRASE = "your_actual_passphrase"
```
## 使用方法
### 1. 演示版本(推荐新手)
如果你还没有OKX API密钥可以先运行演示版本
```bash
python demo.py
```
演示版本功能:
- 使用模拟数据演示策略逻辑
- 无需API密钥即可运行
- 支持策略回测和收益分析
- 适合学习和测试策略
### 2. 实盘版本需要API密钥
配置好API密钥后运行实盘版本
```bash
python play.py
```
运行后会显示菜单,你可以选择:
- 查看账户余额
- 查看当前价格
- 执行各种交易策略
- 运行策略循环
### 2. 策略循环运行
选择菜单中的"6. 运行策略循环",然后:
- 选择策略类型sma/rsi/grid
- 设置执行间隔(秒)
### 3. 配置交易参数
`config.py` 中可以调整:
- 交易数量
- 策略参数
- 风险控制设置
- 时间间隔
## 重要提醒
⚠️ **风险警告**
- 加密货币交易存在高风险
- 建议先在沙盒环境测试
- 实盘交易前请充分了解风险
- 不要投入超过承受能力的资金
🔧 **技术提醒**
- 默认使用沙盒环境(`sandbox=True`
- 实盘交易请将 `sandbox` 设置为 `False`
- 确保API密钥有交易权限
- 建议设置IP白名单
## 文件结构
```
playground/
├── play.py # 主程序文件需要API密钥
├── demo.py # 演示版本无需API密钥
├── config.py # 配置文件
├── test_connection.py # API连接测试
├── requirements.txt # 依赖包列表
└── README.md # 说明文档
```
## 策略参数说明
### 移动平均线策略
- `sma_short_period`: 短期均线周期默认5
- `sma_long_period`: 长期均线周期默认20
### RSI策略
- `rsi_period`: RSI计算周期默认14
- `rsi_oversold`: 超卖阈值默认30
- `rsi_overbought`: 超买阈值默认70
### 网格交易策略
- `grid_levels`: 网格数量默认5
- `grid_range`: 网格范围百分比默认2%
## 常见问题
### Q: 如何切换到实盘交易?
A: 在 `config.py` 中将 `"sandbox": True` 改为 `"sandbox": False`
### Q: 如何调整交易数量?
A: 修改 `config.py` 中的 `"position_size"` 参数
### Q: API调用失败怎么办
A: 检查API密钥是否正确网络连接是否正常API权限是否足够
### Q: 如何添加新的交易策略?
A: 在 `BitcoinQuantTrader` 类中添加新的策略方法,并在菜单中集成
## 免责声明
本软件仅供学习和研究使用,不构成投资建议。使用本软件进行交易的风险由用户自行承担。作者不对任何投资损失负责。
## 许可证
MIT License

Binary file not shown.

37
config.py Normal file
View File

@ -0,0 +1,37 @@
# OKX API 配置
# 请将以下信息替换为你的实际API密钥
# API密钥配置
API_KEY = "your_api_key_here"
SECRET_KEY = "your_secret_key_here"
PASSPHRASE = "your_passphrase_here"
# 交易配置
TRADING_CONFIG = {
"symbol": "BTC-USDT", # 交易对
"position_size": 0.001, # 每次交易数量BTC
"sandbox": True, # 是否使用沙盒环境(建议先用沙盒测试)
# 策略参数
"sma_short_period": 5, # 短期移动平均线周期
"sma_long_period": 20, # 长期移动平均线周期
"rsi_period": 14, # RSI计算周期
"rsi_oversold": 30, # RSI超卖阈值
"rsi_overbought": 70, # RSI超买阈值
# 网格交易参数
"grid_levels": 5, # 网格数量
"grid_range": 0.02, # 网格范围2%
# 风险控制
"max_position": 0.01, # 最大持仓量BTC
"stop_loss_pct": 0.05, # 止损百分比5%
"take_profit_pct": 0.10, # 止盈百分比10%
}
# 时间间隔配置
TIME_CONFIG = {
"strategy_interval": 60, # 策略执行间隔(秒)
"kline_interval": "5m", # K线数据间隔
"kline_limit": 100, # K线数据条数
}

306
demo.py Normal file
View File

@ -0,0 +1,306 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
比特币量化交易系统 - 演示版本
无需API密钥仅用于演示策略逻辑
"""
import pandas as pd
import numpy as np
import time
from datetime import datetime, timedelta
import random
class BitcoinQuantTraderDemo:
def __init__(self):
"""初始化演示版交易器"""
self.symbol = "BTC-USDT"
self.position_size = 0.001 # 每次交易0.001 BTC
self.current_position = 0 # 当前持仓
self.cash = 10000 # 初始资金USDT
self.trades = [] # 交易记录
def generate_mock_data(self, days=30):
"""生成模拟的BTC价格数据"""
print("生成模拟BTC价格数据...")
# 生成时间序列
end_date = datetime.now()
start_date = end_date - timedelta(days=days)
dates = pd.date_range(start=start_date, end=end_date, freq='5min')
# 生成价格数据模拟真实BTC价格波动
np.random.seed(42) # 固定随机种子,确保结果可重现
# 基础价格
base_price = 118000
prices = []
for i in range(len(dates)):
# 添加随机波动
change = np.random.normal(0, 0.002) # 0.2%的标准差
if i == 0:
price = base_price
else:
price = prices[-1] * (1 + change)
prices.append(price)
# 创建DataFrame
df = pd.DataFrame({
'timestamp': dates,
'open': prices,
'high': [p * (1 + abs(np.random.normal(0, 0.001))) for p in prices],
'low': [p * (1 - abs(np.random.normal(0, 0.001))) for p in prices],
'close': prices,
'volume': [np.random.uniform(100, 1000) for _ in prices]
})
# 确保high >= close >= low
df['high'] = df[['open', 'high', 'close']].max(axis=1)
df['low'] = df[['open', 'low', 'close']].min(axis=1)
print(f"生成了 {len(df)} 条价格数据")
print(f"价格范围: ${df['close'].min():.2f} - ${df['close'].max():.2f}")
return df
def calculate_sma(self, df, period=20):
"""计算简单移动平均线"""
return df['close'].rolling(window=period).mean()
def calculate_rsi(self, df, period=14):
"""计算RSI指标"""
delta = df['close'].diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
rsi = 100 - (100 / (1 + rs))
return rsi
def place_mock_order(self, side, size, price):
"""模拟下单"""
timestamp = datetime.now()
if side == 'buy':
cost = size * price
if cost <= self.cash:
self.cash -= cost
self.current_position += size
print(f"✅ 买入成功: {size} BTC @ ${price:.2f}")
self.trades.append({
'timestamp': timestamp,
'side': side,
'size': size,
'price': price,
'cost': cost
})
return True
else:
print(f"❌ 买入失败: 资金不足 (需要: ${cost:.2f}, 可用: ${self.cash:.2f})")
return False
else: # sell
if self.current_position >= size:
revenue = size * price
self.cash += revenue
self.current_position -= size
print(f"✅ 卖出成功: {size} BTC @ ${price:.2f}")
self.trades.append({
'timestamp': timestamp,
'side': side,
'size': size,
'price': price,
'revenue': revenue
})
return True
else:
print(f"❌ 卖出失败: 持仓不足 (需要: {size} BTC, 持有: {self.current_position} BTC)")
return False
def simple_moving_average_strategy(self, df):
"""简单移动平均线策略"""
print("\n=== 执行移动平均线策略 ===")
if len(df) < 20:
print("数据不足,无法执行策略")
return
# 计算移动平均线
df['sma_short'] = self.calculate_sma(df, 5) # 短期均线
df['sma_long'] = self.calculate_sma(df, 20) # 长期均线
# 获取最新数据
latest = df.iloc[-1]
prev = df.iloc[-2]
print(f"短期均线: {latest['sma_short']:.2f}")
print(f"长期均线: {latest['sma_long']:.2f}")
print(f"当前价格: {latest['close']:.2f}")
# 策略逻辑:短期均线上穿长期均线买入,下穿卖出
if (latest['sma_short'] > latest['sma_long'] and
prev['sma_short'] <= prev['sma_long']):
print("信号: 买入")
self.place_mock_order('buy', self.position_size, latest['close'])
elif (latest['sma_short'] < latest['sma_long'] and
prev['sma_short'] >= prev['sma_long']):
print("信号: 卖出")
self.place_mock_order('sell', self.position_size, latest['close'])
else:
print("信号: 持仓观望")
def rsi_strategy(self, df):
"""RSI策略"""
print("\n=== 执行RSI策略 ===")
if len(df) < 30:
print("数据不足,无法执行策略")
return
# 计算RSI
df['rsi'] = self.calculate_rsi(df, 14)
# 获取最新RSI值
latest = df.iloc[-1]
latest_rsi = latest['rsi']
print(f"当前RSI: {latest_rsi:.2f}")
print(f"当前价格: {latest['close']:.2f}")
# 策略逻辑RSI < 30 超卖买入RSI > 70 超买卖出
if latest_rsi < 30:
print("信号: RSI超卖买入")
self.place_mock_order('buy', self.position_size, latest['close'])
elif latest_rsi > 70:
print("信号: RSI超买卖出")
self.place_mock_order('sell', self.position_size, latest['close'])
else:
print("信号: RSI正常区间持仓观望")
def grid_trading_strategy(self, df, grid_levels=5, grid_range=0.02):
"""网格交易策略"""
print(f"\n=== 执行网格交易策略 (网格数: {grid_levels}, 范围: {grid_range*100}%) ===")
if len(df) < 10:
print("数据不足,无法执行策略")
return
current_price = df['close'].iloc[-1]
# 计算网格价格
grid_prices = []
for i in range(grid_levels):
price = current_price * (1 + grid_range * (i - grid_levels//2) / grid_levels)
grid_prices.append(price)
print(f"网格价格: {[f'${p:.2f}' for p in grid_prices]}")
print(f"当前价格: ${current_price:.2f}")
# 找到最近的网格
closest_grid = min(grid_prices, key=lambda x: abs(x - current_price))
grid_index = grid_prices.index(closest_grid)
print(f"最近网格: ${closest_grid:.2f}")
# 简单的网格策略:价格下跌到网格线买入,上涨到网格线卖出
if current_price < closest_grid * 0.995: # 价格下跌超过0.5%
print("信号: 价格下跌,网格买入")
self.place_mock_order('buy', self.position_size, current_price)
elif current_price > closest_grid * 1.005: # 价格上涨超过0.5%
print("信号: 价格上涨,网格卖出")
self.place_mock_order('sell', self.position_size, current_price)
else:
print("信号: 价格在网格内,持仓观望")
def show_portfolio_status(self):
"""显示投资组合状态"""
print("\n" + "="*50)
print("📊 投资组合状态")
print("="*50)
print(f"现金余额: ${self.cash:.2f}")
print(f"BTC持仓: {self.current_position:.6f} BTC")
if self.trades:
# 计算总收益
total_cost = sum(t['cost'] for t in self.trades if 'cost' in t)
total_revenue = sum(t['revenue'] for t in self.trades if 'revenue' in t)
net_profit = total_revenue - total_cost
print(f"总交易次数: {len(self.trades)}")
print(f"总投入: ${total_cost:.2f}")
print(f"总收入: ${total_revenue:.2f}")
print(f"净收益: ${net_profit:.2f}")
if total_cost > 0:
roi = (net_profit / total_cost) * 100
print(f"收益率: {roi:.2f}%")
else:
print("暂无交易记录")
print("="*50)
def run_strategy_backtest(self, strategy='sma', days=30):
"""运行策略回测"""
print(f"🚀 开始运行{strategy}策略回测 ({days}天数据)")
# 生成模拟数据
df = self.generate_mock_data(days)
# 重置投资组合
self.cash = 10000
self.current_position = 0
self.trades = []
# 运行策略
if strategy == 'sma':
self.simple_moving_average_strategy(df)
elif strategy == 'rsi':
self.rsi_strategy(df)
elif strategy == 'grid':
self.grid_trading_strategy(df)
else:
print("未知策略")
return
# 显示结果
self.show_portfolio_status()
# 显示交易记录
if self.trades:
print("\n📋 交易记录:")
for i, trade in enumerate(self.trades, 1):
print(f"{i}. {trade['timestamp'].strftime('%Y-%m-%d %H:%M')} "
f"{trade['side'].upper()} {trade['size']} BTC @ ${trade['price']:.2f}")
def main():
"""主函数"""
print("=== 比特币量化交易系统 - 演示版本 ===")
print("⚠️ 此版本使用模拟数据,仅用于演示策略逻辑")
trader = BitcoinQuantTraderDemo()
while True:
print("\n请选择操作:")
print("1. 运行移动平均线策略回测")
print("2. 运行RSI策略回测")
print("3. 运行网格交易策略回测")
print("4. 查看投资组合状态")
print("0. 退出")
choice = input("请输入选择 (0-4): ").strip()
if choice == '0':
print("退出程序")
break
elif choice == '1':
days = int(input("设置回测天数 (默认30): ") or "30")
trader.run_strategy_backtest('sma', days)
elif choice == '2':
days = int(input("设置回测天数 (默认30): ") or "30")
trader.run_strategy_backtest('rsi', days)
elif choice == '3':
days = int(input("设置回测天数 (默认30): ") or "30")
trader.run_strategy_backtest('grid', days)
elif choice == '4':
trader.show_portfolio_status()
else:
print("无效选择,请重新输入")
if __name__ == "__main__":
main()

334
play.py Normal file
View File

@ -0,0 +1,334 @@
import okx.api.account as Account
import okx.api.trade as Trade
import okx.api.market as Market
import okx.api.public as Public
import pandas as pd
import numpy as np
import time
from datetime import datetime
import json
class BitcoinQuantTrader:
def __init__(self, api_key, secret_key, passphrase, sandbox=True):
"""
初始化比特币量化交易器
Args:
api_key: OKX API Key
secret_key: OKX Secret Key
passphrase: OKX API Passphrase
sandbox: 是否使用沙盒环境建议先用沙盒测试
"""
self.api_key = api_key
self.secret_key = secret_key
self.passphrase = passphrase
# 初始化API客户端
flag = "0" if sandbox else "1" # 0:沙盒环境 1:实盘环境
self.account_api = Account.Account(
api_key, secret_key, passphrase,
flag=flag, debug=False
)
self.trade_api = Trade.Trade(
api_key, secret_key, passphrase,
flag=flag, debug=False
)
self.market_api = Market.Market(
api_key, secret_key, passphrase,
flag=flag, debug=False
)
self.public_api = Public.Public(
api_key, secret_key, passphrase,
flag=flag, debug=False
)
self.symbol = "BTC-USDT"
self.position_size = 0.001 # 每次交易0.001 BTC
def get_account_balance(self):
"""获取账户余额"""
try:
result = self.account_api.get_account_balance()
if result['code'] == '0':
balances = result['data']
for balance in balances:
if balance['ccy'] == 'USDT':
print(f"USDT余额: {balance['bal']}")
return float(balance['bal'])
elif balance['ccy'] == 'BTC':
print(f"BTC余额: {balance['bal']}")
return float(balance['bal'])
else:
print(f"获取余额失败: {result}")
return 0
except Exception as e:
print(f"获取余额异常: {e}")
return 0
def get_current_price(self):
"""获取当前BTC价格"""
try:
result = self.market_api.get_ticker(instId=self.symbol)
if result['code'] == '0':
price = float(result['data'][0]['last'])
print(f"当前BTC价格: ${price:,.2f}")
return price
else:
print(f"获取价格失败: {result}")
return None
except Exception as e:
print(f"获取价格异常: {e}")
return None
def get_kline_data(self, bar='1m', limit=100):
"""获取K线数据"""
try:
result = self.market_api.get_candlesticks(
instId=self.symbol,
bar=bar,
limit=str(limit)
)
if result['code'] == '0':
# 转换为DataFrame
df = pd.DataFrame(result['data'], columns=[
'timestamp', 'open', 'high', 'low', 'close', 'volume', 'volCcy'
])
# 转换数据类型
for col in ['open', 'high', 'low', 'close', 'volume']:
df[col] = pd.to_numeric(df[col])
df['timestamp'] = pd.to_datetime(df['timestamp'].astype(int), unit='ms')
return df
else:
print(f"获取K线数据失败: {result}")
return None
except Exception as e:
print(f"获取K线数据异常: {e}")
return None
def calculate_sma(self, df, period=20):
"""计算简单移动平均线"""
return df['close'].rolling(window=period).mean()
def calculate_rsi(self, df, period=14):
"""计算RSI指标"""
delta = df['close'].diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
rsi = 100 - (100 / (1 + rs))
return rsi
def place_market_order(self, side, size):
"""下市价单"""
try:
result = self.trade_api.place_order(
instId=self.symbol,
tdMode='cash',
side=side,
ordType='market',
sz=str(size)
)
if result['code'] == '0':
print(f"下单成功: {side} {size} BTC")
return result['data'][0]['ordId']
else:
print(f"下单失败: {result}")
return None
except Exception as e:
print(f"下单异常: {e}")
return None
def simple_moving_average_strategy(self):
"""简单移动平均线策略"""
print("\n=== 执行移动平均线策略 ===")
# 获取K线数据
df = self.get_kline_data(bar='5m', limit=50)
if df is None or len(df) < 20:
print("数据不足,无法执行策略")
return
# 计算移动平均线
df['sma_short'] = self.calculate_sma(df, 5) # 短期均线
df['sma_long'] = self.calculate_sma(df, 20) # 长期均线
# 获取最新数据
latest = df.iloc[-1]
prev = df.iloc[-2]
print(f"短期均线: {latest['sma_short']:.2f}")
print(f"长期均线: {latest['sma_long']:.2f}")
print(f"当前价格: {latest['close']:.2f}")
# 策略逻辑:短期均线上穿长期均线买入,下穿卖出
if (latest['sma_short'] > latest['sma_long'] and
prev['sma_short'] <= prev['sma_long']):
print("信号: 买入")
self.place_market_order('buy', self.position_size)
elif (latest['sma_short'] < latest['sma_long'] and
prev['sma_short'] >= prev['sma_long']):
print("信号: 卖出")
self.place_market_order('sell', self.position_size)
else:
print("信号: 持仓观望")
def rsi_strategy(self):
"""RSI策略"""
print("\n=== 执行RSI策略 ===")
# 获取K线数据
df = self.get_kline_data(bar='5m', limit=50)
if df is None or len(df) < 30:
print("数据不足,无法执行策略")
return
# 计算RSI
df['rsi'] = self.calculate_rsi(df, 14)
# 获取最新RSI值
latest_rsi = df['rsi'].iloc[-1]
print(f"当前RSI: {latest_rsi:.2f}")
# 策略逻辑RSI < 30 超卖买入RSI > 70 超买卖出
if latest_rsi < 30:
print("信号: RSI超卖买入")
self.place_market_order('buy', self.position_size)
elif latest_rsi > 70:
print("信号: RSI超买卖出")
self.place_market_order('sell', self.position_size)
else:
print("信号: RSI正常区间持仓观望")
def grid_trading_strategy(self, grid_levels=5, grid_range=0.02):
"""网格交易策略"""
print(f"\n=== 执行网格交易策略 (网格数: {grid_levels}, 范围: {grid_range*100}%) ===")
current_price = self.get_current_price()
if current_price is None:
return
# 计算网格价格
grid_prices = []
for i in range(grid_levels):
price = current_price * (1 + grid_range * (i - grid_levels//2) / grid_levels)
grid_prices.append(price)
print(f"网格价格: {[f'${p:.2f}' for p in grid_prices]}")
# 获取K线数据判断当前价格在哪个网格
df = self.get_kline_data(bar='1m', limit=10)
if df is None:
return
latest_price = df['close'].iloc[-1]
# 找到最近的网格
closest_grid = min(grid_prices, key=lambda x: abs(x - latest_price))
grid_index = grid_prices.index(closest_grid)
print(f"当前价格: ${latest_price:.2f}, 最近网格: ${closest_grid:.2f}")
# 简单的网格策略:价格下跌到网格线买入,上涨到网格线卖出
if latest_price < closest_grid * 0.995: # 价格下跌超过0.5%
print("信号: 价格下跌,网格买入")
self.place_market_order('buy', self.position_size)
elif latest_price > closest_grid * 1.005: # 价格上涨超过0.5%
print("信号: 价格上涨,网格卖出")
self.place_market_order('sell', self.position_size)
else:
print("信号: 价格在网格内,持仓观望")
def run_strategy_loop(self, strategy='sma', interval=60):
"""运行策略循环"""
print(f"开始运行{strategy}策略,间隔{interval}")
while True:
try:
print(f"\n{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# 检查账户余额
self.get_account_balance()
# 执行策略
if strategy == 'sma':
self.simple_moving_average_strategy()
elif strategy == 'rsi':
self.rsi_strategy()
elif strategy == 'grid':
self.grid_trading_strategy()
else:
print("未知策略")
break
print(f"等待{interval}秒后继续...")
time.sleep(interval)
except KeyboardInterrupt:
print("\n策略运行被用户中断")
break
except Exception as e:
print(f"策略运行异常: {e}")
time.sleep(interval)
def main():
"""主函数"""
print("=== 比特币量化交易系统 ===")
# 导入配置
try:
from config import API_KEY, SECRET_KEY, PASSPHRASE, TRADING_CONFIG, TIME_CONFIG
except ImportError:
print("错误找不到config.py文件请确保配置文件存在")
return
# 检查是否配置了API密钥
if API_KEY == "your_api_key_here":
print("请先在config.py中配置你的OKX API密钥")
print("1. 登录OKX官网")
print("2. 进入API管理页面")
print("3. 创建API Key、Secret Key和Passphrase")
print("4. 将密钥填入config.py文件中的相应位置")
return
# 创建交易器实例
trader = BitcoinQuantTrader(
API_KEY, SECRET_KEY, PASSPHRASE,
sandbox=TRADING_CONFIG["sandbox"]
)
# 显示菜单
while True:
print("\n请选择操作:")
print("1. 查看账户余额")
print("2. 查看当前价格")
print("3. 执行移动平均线策略")
print("4. 执行RSI策略")
print("5. 执行网格交易策略")
print("6. 运行策略循环")
print("0. 退出")
choice = input("请输入选择 (0-6): ").strip()
if choice == '0':
print("退出程序")
break
elif choice == '1':
trader.get_account_balance()
elif choice == '2':
trader.get_current_price()
elif choice == '3':
trader.simple_moving_average_strategy()
elif choice == '4':
trader.rsi_strategy()
elif choice == '5':
trader.grid_trading_strategy()
elif choice == '6':
strategy = input("选择策略 (sma/rsi/grid): ").strip()
interval = int(input("设置间隔秒数 (默认60): ") or "60")
trader.run_strategy_loop(strategy, interval)
else:
print("无效选择,请重新输入")
if __name__ == "__main__":
main()

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
okx>=2.1.2
pandas>=2.0.0
numpy>=1.20.0
requests>=2.25.0

129
test_connection.py Normal file
View File

@ -0,0 +1,129 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
OKX API 连接测试脚本
用于验证API密钥配置是否正确以及网络连接是否正常
"""
import okx.api.market as Market
import okx.api.account as Account
from config import API_KEY, SECRET_KEY, PASSPHRASE, TRADING_CONFIG
def test_public_api():
"""测试公共API无需密钥"""
print("=== 测试公共API ===")
try:
# 创建市场数据API实例公共API
market_api = Market.Market()
# 获取BTC-USDT行情
result = market_api.get_ticker(instId="BTC-USDT")
if result['code'] == '0':
price = float(result['data'][0]['last'])
print(f"✅ 公共API测试成功")
print(f"BTC/USDT 当前价格: ${price:,.2f}")
return True
else:
print(f"❌ 公共API测试失败: {result}")
return False
except Exception as e:
print(f"❌ 公共API测试异常: {e}")
return False
def test_private_api():
"""测试私有API需要密钥"""
print("\n=== 测试私有API ===")
try:
# 检查API密钥是否已配置
if API_KEY == "your_api_key_here":
print("⚠️ API密钥未配置跳过私有API测试")
print("请在config.py中配置你的API密钥")
return False
# 创建账户API实例
flag = "0" if TRADING_CONFIG["sandbox"] else "1"
account_api = Account.Account(
API_KEY, SECRET_KEY, PASSPHRASE,
flag=flag, debug=False
)
# 获取账户余额
result = account_api.get_account_balance()
if result['code'] == '0':
print("✅ 私有API测试成功")
print("账户余额信息:")
for balance in result['data']:
if balance['ccy'] in ['USDT', 'BTC']:
print(f" {balance['ccy']}: {balance['bal']}")
return True
else:
print(f"❌ 私有API测试失败: {result}")
if result['code'] == '50001':
print("可能原因: API密钥错误或权限不足")
elif result['code'] == '50002':
print("可能原因: 签名错误")
elif result['code'] == '50004':
print("可能原因: 请求过于频繁")
return False
except Exception as e:
print(f"❌ 私有API测试异常: {e}")
return False
def test_environment():
"""测试环境配置"""
print("\n=== 测试环境配置 ===")
print(f"沙盒环境: {'' if TRADING_CONFIG['sandbox'] else ''}")
print(f"交易对: {TRADING_CONFIG['symbol']}")
print(f"交易数量: {TRADING_CONFIG['position_size']} BTC")
# 检查依赖包
try:
import pandas as pd
import numpy as np
print("✅ 依赖包检查通过")
except ImportError as e:
print(f"❌ 依赖包缺失: {e}")
print("请运行: pip install pandas numpy")
return False
return True
def main():
"""主测试函数"""
print("🚀 OKX API 连接测试")
print("=" * 50)
# 测试环境配置
env_ok = test_environment()
# 测试公共API
public_ok = test_public_api()
# 测试私有API
private_ok = test_private_api()
# 总结
print("\n" + "=" * 50)
print("📊 测试结果总结:")
print(f"环境配置: {'✅ 通过' if env_ok else '❌ 失败'}")
print(f"公共API: {'✅ 通过' if public_ok else '❌ 失败'}")
print(f"私有API: {'✅ 通过' if private_ok else '❌ 失败'}")
if env_ok and public_ok:
print("\n🎉 基础功能测试通过!可以运行主程序了。")
if private_ok:
print("🔐 API密钥配置正确可以进行交易操作。")
else:
print("⚠️ API密钥需要配置或有问题只能使用公共功能。")
else:
print("\n❌ 存在配置问题,请检查后重试。")
if __name__ == "__main__":
main()