feat: 添加前端界面和市场分析模块
- 新增 Vue 3 + Vuetify 前端界面 - 新增市场分析模块 (market/) - 更新主服务器和路由 - 更新 MT5 EA 文件 - 添加 .gitignore 排除临时文件
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
行情API调用示例
|
||||
|
||||
演示EA端如何推送K线数据到Python服务
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
import random
|
||||
|
||||
# 服务地址
|
||||
BASE_URL = "http://localhost:8000"
|
||||
|
||||
|
||||
def generate_mock_klines(count: int, base_price: float, period_minutes: int) -> list:
|
||||
"""
|
||||
生成模拟K线数据
|
||||
"""
|
||||
klines = []
|
||||
now = datetime.now()
|
||||
|
||||
for i in range(count):
|
||||
# 计算时间戳
|
||||
ts = now - timedelta(minutes=period_minutes * (count - i - 1))
|
||||
|
||||
# 生成随机价格波动
|
||||
change = random.uniform(-0.01, 0.01) * base_price
|
||||
open_price = base_price + change
|
||||
high = open_price + random.uniform(0, 0.005) * base_price
|
||||
low = open_price - random.uniform(0, 0.005) * base_price
|
||||
close = open_price + random.uniform(-0.003, 0.003) * base_price
|
||||
|
||||
klines.append({
|
||||
"timestamp": ts.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"open": round(open_price, 2),
|
||||
"high": round(high, 2),
|
||||
"low": round(low, 2),
|
||||
"close": round(close, 2),
|
||||
"volume": random.randint(100, 1000)
|
||||
})
|
||||
|
||||
# 更新基准价格
|
||||
base_price = close
|
||||
|
||||
return klines
|
||||
|
||||
|
||||
def push_kline_single_period(symbol: str, period: str, klines: list, is_full: bool = False):
|
||||
"""
|
||||
推送单个周期的K线数据
|
||||
"""
|
||||
url = f"{BASE_URL}/ea/kline/{period}"
|
||||
|
||||
payload = {
|
||||
"symbol": symbol,
|
||||
"is_full": is_full,
|
||||
"klines": klines
|
||||
}
|
||||
|
||||
print(f"\n推送 {symbol} {period} K线数据 ({len(klines)} 条, {'全量' if is_full else '增量'})")
|
||||
|
||||
try:
|
||||
response = requests.post(url, json=payload)
|
||||
print(f"状态码: {response.status_code}")
|
||||
print(f"响应: {response.json()}")
|
||||
|
||||
# 检查是否需要全量数据
|
||||
if response.status_code == 400:
|
||||
data = response.json()
|
||||
if data.get('code') == 8888:
|
||||
print(">>> 服务需要全量数据,请重新发送历史数据")
|
||||
return 8888
|
||||
|
||||
return response.status_code
|
||||
|
||||
except Exception as e:
|
||||
print(f"请求失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def push_kline_batch(symbol: str, kline_data: dict, is_full: bool = False):
|
||||
"""
|
||||
批量推送多个周期的K线数据
|
||||
"""
|
||||
url = f"{BASE_URL}/ea/kline_batch"
|
||||
|
||||
payload = {
|
||||
"symbol": symbol,
|
||||
"is_full": is_full,
|
||||
"data": kline_data
|
||||
}
|
||||
|
||||
print(f"\n批量推送 {symbol} K线数据 ({'全量' if is_full else '增量'})")
|
||||
|
||||
try:
|
||||
response = requests.post(url, json=payload)
|
||||
print(f"状态码: {response.status_code}")
|
||||
print(f"响应: {json.dumps(response.json(), indent=2, ensure_ascii=False)}")
|
||||
return response.status_code
|
||||
|
||||
except Exception as e:
|
||||
print(f"请求失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_trades_with_price(symbol: str, price: float):
|
||||
"""
|
||||
获取交易指令(携带价格,用于转折点检测)
|
||||
"""
|
||||
url = f"{BASE_URL}/get_trades"
|
||||
params = {
|
||||
"symbol": symbol,
|
||||
"price": price
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(url, params=params)
|
||||
data = response.json()
|
||||
|
||||
print(f"\n获取 {symbol} 交易指令 (价格: {price})")
|
||||
print(f"交易指令: {data.get('trades', [])}")
|
||||
|
||||
# 检查转折点提醒
|
||||
alerts = data.get('pivot_alerts', [])
|
||||
if alerts:
|
||||
print(f"\n⚠️ 转折点提醒 ({len(alerts)} 条):")
|
||||
for alert in alerts:
|
||||
print(f" - {alert['period']} {alert['direction'] == 'high' and '高点' or '低点'}")
|
||||
print(f" 转折点价格: {alert['pivot_price']}")
|
||||
print(f" 当前价格: {alert['current_price']}")
|
||||
print(f" 距离: {alert['distance_pct']}%")
|
||||
else:
|
||||
print("无转折点提醒")
|
||||
|
||||
return data
|
||||
|
||||
except Exception as e:
|
||||
print(f"请求失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_klines(symbol: str, period: str, count: int = 100):
|
||||
"""查询K线数据"""
|
||||
url = f"{BASE_URL}/market/kline/{symbol}"
|
||||
params = {"period": period, "count": count}
|
||||
|
||||
try:
|
||||
response = requests.get(url, params=params)
|
||||
data = response.json()
|
||||
print(f"\n{symbol} {period} K线数据 ({data['count']} 条):")
|
||||
for k in data['data'][-3:]:
|
||||
print(f" {k['timestamp']}: O={k['open']} H={k['high']} L={k['low']} C={k['close']}")
|
||||
return data
|
||||
|
||||
except Exception as e:
|
||||
print(f"请求失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def get_pivots(symbol: str):
|
||||
"""查询转折点"""
|
||||
url = f"{BASE_URL}/market/pivots/{symbol}"
|
||||
|
||||
try:
|
||||
response = requests.get(url)
|
||||
data = response.json()
|
||||
print(f"\n{symbol} 转折点数据:")
|
||||
for period, pivots in data.get('data', {}).items():
|
||||
if pivots:
|
||||
print(f" {period}: {len(pivots)} 个转折点")
|
||||
for p in pivots[:3]:
|
||||
print(f" - {p['direction'] == 'high' and '高点' or '低点'} @ {p['price']} ({p['timestamp']})")
|
||||
return data
|
||||
|
||||
except Exception as e:
|
||||
print(f"请求失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
演示完整的EA启动流程
|
||||
"""
|
||||
print("=" * 60)
|
||||
print("EA 行情数据推送示例")
|
||||
print("=" * 60)
|
||||
|
||||
symbol = "GOLD"
|
||||
base_price = 2030.0
|
||||
|
||||
# ==================== 1. EA启动时推送全量K线数据 ====================
|
||||
print("\n[步骤1] EA启动,推送全量K线数据...")
|
||||
|
||||
# 各周期历史数据条数(根据实际需求)
|
||||
history_counts = {
|
||||
'H4': 1100, # 6个月约1100根4小时K线
|
||||
'H1': 720, # 1个月约720根1小时K线
|
||||
'M15': 288, # 3天约288根15分钟K线
|
||||
'M5': 288, # 24小时288根5分钟K线
|
||||
'M1': 60 # 1小时60根1分钟K线
|
||||
}
|
||||
|
||||
kline_data = {}
|
||||
period_minutes = {'H4': 240, 'H1': 60, 'M15': 15, 'M5': 5, 'M1': 1}
|
||||
|
||||
for period, count in history_counts.items():
|
||||
kline_data[period] = generate_mock_klines(count, base_price, period_minutes[period])
|
||||
|
||||
push_kline_batch(symbol, kline_data, is_full=True)
|
||||
|
||||
# ==================== 2. 查询K线和转折点 ====================
|
||||
print("\n[步骤2] 查询K线数据和转折点...")
|
||||
|
||||
get_klines(symbol, 'H4', 10)
|
||||
get_pivots(symbol)
|
||||
|
||||
# ==================== 3. 模拟EA轮询获取交易指令 ====================
|
||||
print("\n[步骤3] EA轮询获取交易指令(携带当前价格)...")
|
||||
|
||||
# 模拟当前价格
|
||||
current_price = base_price + random.uniform(-5, 5)
|
||||
get_trades_with_price(symbol, current_price)
|
||||
|
||||
# ==================== 4. 模拟增量数据推送 ====================
|
||||
print("\n[步骤4] 推送增量K线数据...")
|
||||
|
||||
# 生成一根新的K线
|
||||
for period in ['H4', 'H1', 'M15', 'M5', 'M1']:
|
||||
new_klines = generate_mock_klines(1, base_price, period_minutes[period])
|
||||
push_kline_single_period(symbol, period, new_klines, is_full=False)
|
||||
|
||||
# ==================== 5. 查看服务状态 ====================
|
||||
print("\n[步骤5] 查看服务状态...")
|
||||
|
||||
try:
|
||||
response = requests.get(f"{BASE_URL}/market/status")
|
||||
data = response.json()
|
||||
print(json.dumps(data, indent=2, ensure_ascii=False))
|
||||
except Exception as e:
|
||||
print(f"请求失败: {e}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("示例完成")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user