You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
8.5 KiB

# Service main application
from flask import Flask, request, jsonify
import sys
import os
import pandas as pd
# 添加项目根目录到 Python 路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from qihuo_analyzer.data.data_fetcher import DataFetcher
from qihuo_analyzer.data.data_storage import DataStorage
from qihuo_analyzer.modules.deepseek_agent import DeepseekAgent
from qihuo_analyzer.utils.config_manager import config_manager
app = Flask(__name__)
# 初始化组件
data_fetcher = DataFetcher()
data_storage = DataStorage()
deepseek_agent = DeepseekAgent()
# 连接 API
print("正在连接 API...")
connect_success = data_fetcher.connect()
if connect_success:
print("API 连接成功,可以获取真实数据")
else:
print("API 连接失败,将使用模拟数据")
# 健康检查接口
@app.route('/health', methods=['GET'])
def health_check():
return jsonify({'status': 'ok', 'message': 'Service is running'})
# 合约数据获取接口
@app.route('/api/contracts', methods=['GET'])
def get_contracts():
try:
exchange = request.args.get('exchange', '')
symbol = request.args.get('symbol', '')
contracts = data_fetcher.get_contracts(exchange=exchange, symbol=symbol)
return jsonify({'status': 'success', 'data': contracts})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# K线数据获取接口
@app.route('/api/kline', methods=['GET'])
def get_kline():
try:
symbol = request.args.get('symbol', '')
duration = request.args.get('duration', '1m')
limit = int(request.args.get('limit', 100))
if not symbol:
return jsonify({'status': 'error', 'message': 'Symbol is required'}), 400
# 尝试从数据库获取,如果没有则从数据源获取
df = data_storage.get_kline_data(symbol, duration, limit)
if df.empty:
# 从数据源获取
df = data_fetcher.get_kline_data(symbol, duration, limit)
# 保存到数据库
data_storage.save_kline_data(symbol, duration, df)
# 转换为字典格式
kline_data = []
for idx, row in df.iterrows():
kline_data.append({
'datetime': idx.isoformat(),
'open': float(row['open']),
'high': float(row['high']),
'low': float(row['low']),
'close': float(row['close']),
'volume': int(row['volume']),
'open_interest': int(row['open_interest'])
})
return jsonify({'status': 'success', 'data': kline_data})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# DeepSeek 分析接口
@app.route('/api/analyze', methods=['POST'])
def analyze():
try:
data = request.get_json()
symbol = data.get('symbol', '')
duration = data.get('duration', '1m')
analysis_type = data.get('analysis_type', 'technical')
if not symbol:
return jsonify({'status': 'error', 'message': 'Symbol is required'}), 400
# 获取K线数据
df = data_fetcher.get_kline_data(symbol, duration, 1000)
# 保存到数据库
data_storage.save_kline_data(symbol, duration, df)
# 执行分析
analysis_result = deepseek_agent.analyze_market(symbol, df)
# 保存分析结果
data_storage.save_analysis_result(analysis_result)
return jsonify({'status': 'success', 'data': analysis_result})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# 交易建议接口
@app.route('/api/recommendations', methods=['GET'])
def get_recommendations():
try:
symbol = request.args.get('symbol', '')
status = request.args.get('status', '')
if not symbol:
return jsonify({'status': 'error', 'message': 'Symbol is required'}), 400
df = data_storage.get_trade_recommendations(symbol, status)
# 转换为字典格式
recommendations = []
for _, row in df.iterrows():
recommendations.append({
'id': int(row['id']),
'symbol': row['symbol'],
'timestamp': row['timestamp'],
'direction': row['direction'],
'entry_price': float(row['entry_price']) if not pd.isna(row['entry_price']) else None,
'stop_loss': float(row['stop_loss']) if not pd.isna(row['stop_loss']) else None,
'target_price': float(row['target_price']) if not pd.isna(row['target_price']) else None,
'position_size': float(row['position_size']) if not pd.isna(row['position_size']) else None,
'execution_plan': row['execution_plan'],
'risk_tips': row['risk_tips'],
'status': row['status'],
'created_at': row['created_at']
})
return jsonify({'status': 'success', 'data': recommendations})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# 风险监控接口
@app.route('/api/risk', methods=['POST'])
def monitor_risk():
try:
data = request.get_json()
symbol = data.get('symbol', '')
current_price = data.get('current_price', 0)
entry_price = data.get('entry_price', 0)
stop_loss = data.get('stop_loss', 0)
target_price = data.get('target_price', 0)
if not symbol:
return jsonify({'status': 'error', 'message': 'Symbol is required'}), 400
# 计算当前利润
current_profit = current_price - entry_price
# 评估风险状态
risk_status = 'normal'
if abs(current_profit) > (entry_price * 0.05):
risk_status = 'high'
# 保存风险监控数据
risk_data = {
'symbol': symbol,
'current_price': current_price,
'entry_price': entry_price,
'stop_loss': stop_loss,
'target_price': target_price,
'current_profit': current_profit,
'risk_status': risk_status
}
data_storage.save_risk_monitoring(risk_data)
return jsonify({'status': 'success', 'data': risk_data})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
# 分析历史接口
@app.route('/api/analysis/history', methods=['GET'])
def get_analysis_history():
try:
symbol = request.args.get('symbol', '')
limit = int(request.args.get('limit', 100))
if not symbol:
return jsonify({'status': 'error', 'message': 'Symbol is required'}), 400
df = data_storage.get_analysis_results(symbol, limit)
# 转换为字典格式
history = []
for _, row in df.iterrows():
history.append({
'id': int(row['id']),
'symbol': row['symbol'],
'timestamp': row['timestamp'],
'trend': row['trend'],
'probability': float(row['probability']) if not pd.isna(row['probability']) else None,
'direction': row['direction'],
'cycle': row['cycle'],
'atr': float(row['atr']) if not pd.isna(row['atr']) else None,
'adx': float(row['adx']) if not pd.isna(row['adx']) else None,
'support': float(row['support']) if not pd.isna(row['support']) else None,
'resistance': float(row['resistance']) if not pd.isna(row['resistance']) else None,
'stop_loss': float(row['stop_loss']) if not pd.isna(row['stop_loss']) else None,
'target_price': float(row['target_price']) if not pd.isna(row['target_price']) else None,
'position_size': float(row['position_size']) if not pd.isna(row['position_size']) else None,
'risk_ratio': float(row['risk_ratio']) if not pd.isna(row['risk_ratio']) else None,
'fund_flow': row['fund_flow'],
'signals': row['signals'],
'created_at': row['created_at']
})
return jsonify({'status': 'success', 'data': history})
except Exception as e:
return jsonify({'status': 'error', 'message': str(e)}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)