股票选股与因子回测
تم الإنشاء في: ٣٠ نوفمبر ٢٠٢٤
تمت الإجابة باستخدام O1 Preview بواسطة Chat01
تم الإنشاء في: ٣٠ نوفمبر ٢٠٢٤
تمت الإجابة باستخدام O1 Preview بواسطة Chat01
from jqdata import *
import numpy as np
import pandas as pd
def initialize(context):
# 设置基准
set_benchmark('000300.XSHG')
# 设置滑点
set_slippage(PriceRelatedSlippage(0.002))
# 设置手续费
set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 设置运行时间
run_daily(select_stock, time='15:30', reference_security='000300.XSHG')
run_daily(market_open, time='9:15', reference_security='000300.XSHG')
run_daily(market_close, time='14:57', reference_security='000300.XSHG')
run_daily(after_market_analysis, time='18:00', reference_security='000300.XSHG')
# 初始化全局变量
g.current_stock = None
g.selected_stock = None
def check_strength_conditions(current_strength, prev_strength, daily_change):
"""检查单日数据是否满足关注条件"""
conditions_met = []
text# 条件1: 日强度变化大于3 if daily_change > 3: conditions_met.append("日强度变化大于3") # 条件2: 强度得分大于6且日强度变化大于1.5 if current_strength > 6 and daily_change > 1.5: conditions_met.append("强度得分大于6且日强度变化大于1.5") # 条件3: 强度得分大于10且日强度变化大于1 if current_strength > 10 and daily_change > 1: conditions_met.append("强度得分大于10且日强度变化大于1") # 条件4: 当日强度得分大于13且前日强度得分小于13 if current_strength > 13 and prev_strength < 13: conditions_met.append("当日强度得分大于13且前日强度得分小于13") # 条件5: 强度变化大于6 if daily_change > 6: conditions_met.append("强度变化大于6") return conditions_met
def calculate_single_day_strength(close_data, offset=0):
"""计算单日强度值"""
ma5 = np.mean(close_data[-(5+offset):len(close_data)-offset])
ma13 = np.mean(close_data[-(13+offset):len(close_data)-offset])
ma20 = np.mean(close_data[-(20+offset):len(close_data)-offset])
ma60 = np.mean(close_data[-(60+offset):len(close_data)-offset])
textma5_prev = np.mean(close_data[-(6+offset):len(close_data)-(offset+1)]) ma13_prev = np.mean(close_data[-(14+offset):len(close_data)-(offset+1)]) ma20_prev = np.mean(close_data[-(21+offset):len(close_data)-(offset+1)]) ma60_prev = np.mean(close_data[-(61+offset):len(close_data)-(offset+1)]) ultra_short = np.arctan((ma5/ma5_prev - 1) * 100) * 57.3 short = np.arctan((ma13/ma13_prev - 1) * 100) * 57.3 medium = np.arctan((ma20/ma20_prev - 1) * 100) * 57.3 long = np.arctan((ma60/ma60_prev - 1) * 100) * 57.3 total_strength = (ultra_short/50 + short/40 + medium/21 + long/10) return { 'strength': total_strength, 'ultra_short': ultra_short, 'short': short, 'medium': medium, 'long': long }
def get_stock_strength(context):
"""获取股票强度数据"""
# 获取所有A股
stocks = list(get_all_securities(['stock']).index)
text# 过滤科创板和ST股票 stocks = [s for s in stocks if not ( s.startswith(('688', '689', '833', '837', '870', '871', '872', '873', '920', '430')) or 'ST' in get_security_info(s).display_name )] # 过滤上市不足100天的股票 stocks = [s for s in stocks if ( (context.current_dt.date() - get_security_info(s).start_date).days > 100 )] strength_scores = {} for stock in stocks: try: # 获取过去121个交易日的收盘价 prices = get_price(stock, count=121, end_date=context.current_dt, fields=['close'], skip_paused=False, fq='pre') close = prices['close'].values today_strength = calculate_single_day_strength(close) yesterday_strength = calculate_single_day_strength(close, offset=1) strength_history = [] daily_changes = [] # 获取过去60个交易日的日期列表 trading_dates = prices.index.tolist()[-60:] # 计算60天的历史强度值 for i in range(60): day_strength = calculate_single_day_strength(close, offset=i) strength_history.append({ 'date': trading_dates[-i-1], 'strength': day_strength['strength'] }) # 计算强度变化(当日减去前一日) for i in range(len(strength_history)-1): current_day = strength_history[i] prev_day = strength_history[i+1] daily_changes.append({ 'date': current_day['date'], 'change': current_day['strength'] - prev_day['strength'], 'current_strength': current_day['strength'], 'prev_strength': prev_day['strength'] }) strength_scores[stock] = { 'strength': today_strength['strength'], 'yesterday_strength': yesterday_strength['strength'], 'strength_history': strength_history, 'daily_changes': daily_changes } except Exception as e: continue return strength_scores
def select_stock(context):
"""选股函数"""
# 获取所有A股
stocks = list(get_all_securities(['stock']).index)
text# 过滤科创板和ST股票 stocks = [s for s in stocks if not ( s.startswith(('688', '689', '833', '837', '870', '871', '872', '873', '920', '430')) or 'ST' in get_security_info(s).display_name )] # 过滤上市不足100天的股票 stocks = [s for s in stocks if ( (context.current_dt.date() - get_security_info(s).start_date).days > 100 )] qualified_stocks = [] # 存储符合条件的股票 strength_scores = get_stock_strength(context) # 获取股票强度数据 for stock in stocks: if stock not in strength_scores: continue stock_info = strength_scores[stock] total_strength = stock_info['strength'] prev_strength = stock_info['yesterday_strength'] daily_change = total_strength - prev_strength # 检查条件 if total_strength > 13: conditions_met = check_strength_conditions(total_strength, prev_strength, daily_change) qualified_stocks.append({ 'code': stock, 'name': get_security_info(stock).display_name, 'strength': total_strength, 'conditions_met': conditions_met, 'daily_change': daily_change, 'prev_strength': prev_strength, 'highlight': daily_change > 4, # 标记日强度变化大于4的股票 'star_mark': daily_change > 6 # 标记日强度变化大于6的股票 }) # 输出符合条件的股票汇总 qualified_stocks.sort(key=lambda x: x['strength'], reverse=True) # 按强度得分排序 print("\n=== 符合选市场龙头股公式的股票的股票汇总 ===") for stock in qualified_stocks: highlight_mark = "⭐ [大星号关注]" if stock['star_mark'] else "" print(f"{context.current_dt} 18:00:00 - INFO - 股票代码: {stock['code']} 股票名称: {stock['name']} 强度得分: {stock['strength']:.2f} 日强度变化: {stock['daily_change']:.2f} ({stock['strength']:.2f}-{stock['prev_strength']:.2f}) {highlight_mark}") # 输出最近20个交易日历史数据 for stock in qualified_stocks: stock_data = strength_scores[stock['code']] print(f"\n最近20个交易日历史数据") print(f"{context.current_dt} 15:30:00 - INFO - \n==================================================\n") print(f"{context.current_dt} 15:30:00 - INFO - 股票代码: {stock['code']}\n") print(f"{context.current_dt} 15:30:00 - INFO - 股票名称: {stock['name']}\n") print(f"{context.current_dt} 15:30:00 - INFO - 当前总强度得分: {stock['strength']:.2f}\n") print(f"{context.current_dt} 15:30:00 - INFO - \n最近20个交易日历史数据 日强度变化(当日-前日):\n") # 只取最近20个交易日的数据 recent_changes = stock_data['daily_changes'][:20] for change in recent_changes: date = change['date'] # 检查当前强度和前一日强度是否满足条件 if change['current_strength'] is not None and change['prev_strength'] is not None: # 确保有交易数据 conditions_met = check_strength_conditions(change['current_strength'], change['prev_strength'], change['change']) condition_mark = f" ⭐ [{', '.join(conditions_met)}]" if conditions_met else "" # 获取截止到该日期的成交数据 prices = get_price(stock['code'], count=21, end_date=date, fields=['volume', 'money'], skip_paused=False, fq='pre') volumes = prices['volume'].values money = prices['money'].values if len(volumes) >= 21: # 计算均价 avg1 = money[-1] / volumes[-1] if volumes[-1] != 0 else 0 # 最近1日均价 avg3 = np.sum(money[-3:]) / np.sum(volumes[-3:]) if np.sum(volumes[-3:]) != 0 else 0 # 最近3日均价 avg5 = np.sum(money[-5:]) / np.sum(volumes[-5:]) if np.sum(volumes[-5:]) != 0 else 0 # 最近5日均价 avg10 = np.sum(money[-10:]) / np.sum(volumes[-10:]) if np.sum(volumes[-10:]) != 0 else 0 # 最近10日均价 avg20 = np.sum(money[-20:]) / np.sum(volumes[-20:]) if np.sum(volumes[-20:]) != 0 else 0 # 最近20日均价 # 前一周期的均价 prev_avg1 = money[-2] / volumes[-2] if volumes[-2] != 0 else 0 prev_avg3 = np.sum(money[-4:-1]) / np.sum(volumes[-4:-1]) if np.sum(volumes[-4:-1]) != 0 else 0 prev_avg5 = np.sum(money[-6:-1]) / np.sum(volumes[-6:-1]) if np.sum(volumes[-6:-1]) != 0 else 0 prev_avg10 = np.sum(money[-11:-1]) / np.sum(volumes[-11:-1]) if np.sum(volumes[-11:-1]) != 0 else 0 prev_avg20 = np.sum(money[-21:-1]) / np.sum(volumes[-21:-1]) if np.sum(volumes[-21:-1]) != 0 else 0 # 计算均比 ratio1 = ((avg1 - prev_avg1) / prev_avg1 * 100) if prev_avg1 != 0 else 0 ratio3 = ((avg3 - prev_avg3) / prev_avg3 * 100) if prev_avg3 != 0 else 0 ratio5 = ((avg5 - prev_avg5) / prev_avg5 * 100) if prev_avg5 != 0 else 0 ratio10 = ((avg10 - prev_avg10) / prev_avg10 * 100) if prev_avg10 != 0 else 0 ratio20 = ((avg20 - prev_avg20) / prev_avg20 * 100) if prev_avg20 != 0 else 0 else: # 数据不足,无法计算 avg1 = avg3 = avg5 = avg10 = avg20 = 0 ratio1 = ratio3 = ratio5 = ratio10 = ratio20 = 0 print(f"{context.current_dt} 15:30:00 - INFO - {date.strftime('%Y-%m-%d')}日强度变化: {change['change']:.2f} " f"({change['current_strength']:.2f}-{change['prev_strength']:.2f}){condition_mark} " f"均价1: {avg1:.2f} 均价3: {avg3:.2f} 均价5: {avg5:.2f} 均价10: {avg10:.2f} 均价20: {avg20:.2f} " f"均比1: {ratio1:.2f}% 均比3: {ratio3:.2f}% 均比5: {ratio5:.2f}% 均比10: {ratio10:.2f}% 均比20: {ratio20:.2f}%") g.selected_stock = [stock['code'] for stock in qualified_stocks]
def market_open(context):
"""开盘时执行的函数"""
if g.selected_stock:
current_data = get_current_data()
for stock in g.selected_stock:
up_limit = current_data[stock].high_limit
cash = context.portfolio.available_cash * 0.5 / len(g.selected_stock)
if cash > 0:
order(stock, cash/up_limit, LimitOrderStyle(up_limit))
def market_close(context):
"""收盘前执行的函数"""
positions = context.portfolio.positions
current_data = get_current_data()
textfor stock in positions: current_price = current_data[stock].last_price up_limit = current_data[stock].high_limit if current_price < up_limit: down_limit = current_data[stock].low_limit order(stock, -positions[stock].total_amount, LimitOrderStyle(down_limit))
def after_market_analysis(context):
"""收盘后市场分析"""
current_date = context.current_dt.date()
strength_scores = get_stock_strength(context)
textprint(f"\n{'='*20} {current_date} 市场分析报告 {'='*20}\n") # 新增:输出日强度变化大于2.5且强度得分大于6的股票汇总 strong_change_stocks = [] # 用于存储日强度变化大于2.5且强度得分大于6的股票 for stock_code, stock_info in strength_scores.items(): stock_name = get_security_info(stock_code).display_name latest_history = stock_info['strength_history'][0] latest_change = stock_info['daily_changes'][0] # 检查日强度变化是否大于2.5且强度得分大于6 if latest_change['change'] > 2.5 and latest_history['strength'] > 6: strong_change_stocks.append({ 'code': stock_code, 'name': stock_name, 'strength': latest_history['strength'], 'change': latest_change['change'], 'current_strength': latest_change['current_strength'], 'prev_strength': latest_change['prev_strength'] }) # 输出日强度变化大于2.5且强度得分大于6的股票汇总 if strong_change_stocks: strong_change_stocks = sorted(strong_change_stocks, key=lambda x: (x['change'], x['strength']), reverse=True) # 按日强度变化和强度得分排序 print("=== 日强度变化大于2.5且强度得分大于6的股票汇总 ===\n") for stock in strong_change_stocks: print(f"{current_date} 18:00:00 - INFO - 股票代码: {stock['code']} 股票名称: {stock['name']} " f"强度得分: {stock['strength']:.2f} 日强度变化: {stock['change']:.2f} " f"({stock['current_strength']:.2f}-{stock['prev_strength']:.2f})") else: print("=== 日强度变化大于2.5且强度得分大于6的股票汇总 ===\n暂无符合条件的股票。") # 输出最近20个交易日历史数据 for stock in strong_change_stocks: stock_data = strength_scores[stock['code']] print(f"\n最近20个交易日历史数据\n") print(f"{current_date} 15:30:00 - INFO - \n==================================================\n") print(f"{current_date} 15:30:00 - INFO - 股票代码: {stock['code']}\n") print(f"{current_date} 15:30:00 - INFO - 股票名称: {stock['name']}\n") print(f"{current_date} 15:30:00 - INFO - 当前总强度得分: {stock['strength']:.2f}\n") print(f"{current_date} 15:30:00 - INFO - \n最近20个交易日历史数据 日强度变化(当日-前日):\n") # 只取最近20个交易日的数据 recent_changes = stock_data['daily_changes'][:20] for change in recent_changes: date = change['date'] # 检查当前强度和前一日强度是否满足条件 if change['current_strength'] is not None and change['prev_strength'] is not None: # 确保有交易数据 conditions_met = check_strength_conditions(change['current_strength'], change['prev_strength'], change['change']) condition_mark = f" ⭐ [{', '.join(conditions_met)}]" if conditions_met else "" # 获取截止到该日期的成交数据 prices = get_price(stock['code'], count=21, end_date=date, fields=['volume', 'money'], skip_paused=False, fq='pre') volumes = prices['volume'].values money = prices['money'].values if len(volumes) >= 21: # 计算均价 avg1 = money[-1] / volumes[-1] if volumes[-1] != 0 else 0 # 最近1日均价 avg3 = np.sum(money[-3:]) / np.sum(volumes[-3:]) if np.sum(volumes[-3:]) != 0 else 0 # 最近3日均价 avg5 = np.sum(money[-5:]) / np.sum(volumes[-5:]) if np.sum(volumes[-5:]) != 0 else 0 # 最近5日均价 avg10 = np.sum(money[-10:]) / np.sum(volumes[-10:]) if np.sum(volumes[-10:]) != 0 else 0 # 最近10日均价 avg20 = np.sum(money[-20:]) / np.sum(volumes[-20:]) if np.sum(volumes[-20:]) != 0 else 0 # 最近20日均价 # 前一周期的均价 prev_avg1 = money[-2] / volumes[-2] if volumes[-2] != 0 else 0 prev_avg3 = np.sum(money[-4:-1]) / np.sum(volumes[-4:-1]) if np.sum(volumes[-4:-1]) != 0 else 0 prev_avg5 = np.sum(money[-6:-1]) / np.sum(volumes[-6:-1]) if np.sum(volumes[-6:-1]) != 0 else 0 prev_avg10 = np.sum(money[-11:-1]) / np.sum(volumes[-11:-1]) if np.sum(volumes[-11:-1]) != 0 else 0 prev_avg20 = np.sum(money[-21:-1]) / np.sum(volumes[-21:-1]) if np.sum(volumes[-21:-1]) != 0 else 0 # 计算均比 ratio1 = ((avg1 - prev_avg1) / prev_avg1 * 100) if prev_avg1 != 0 else 0 ratio3 = ((avg3 - prev_avg3) / prev_avg3 * 100) if prev_avg3 != 0 else 0 ratio5 = ((avg5 - prev_avg5) / prev_avg5 * 100) if prev_avg5 != 0 else 0 ratio10 = ((avg10 - prev_avg10) / prev_avg10 * 100) if prev_avg10 != 0 else 0 ratio20 = ((avg20 - prev_avg20) / prev_avg20 * 100) if prev_avg20 != 0 else 0 else: # 数据不足,无法计算 avg1 = avg3 = avg5 = avg10 = avg20 = 0 ratio1 = ratio3 = ratio5 = ratio10 = ratio20 = 0 print(f"{current_date} 15:30:00 - INFO - {date.strftime('%Y-%m-%d')}日强度变化: {change['change']:.2f} " f"({change['current_strength']:.2f}-{change['prev_strength']:.2f}){condition_mark} " f"均价1: {avg1:.2f} 均价3: {avg3:.2f} 均价5: {avg5:.2f} 均价10: {avg10:.2f} 均价20: {avg20:.2f} " f"均比1: {ratio1:.2f}% 均比3: {ratio3:.2f}% 均比5: {ratio5:.2f}% 均比10: {ratio10:.2f}% 均比20: {ratio20:.2f}%") g.selected_stock = [stock['code'] for stock in strong_change_stocks]
1 符合选市场龙头股公式的股票的股票汇总 的数据 要输出
2 不要输出 日强度变化大于2.5且强度得分大于6的股票汇总 的数据3
3 对符合选市场龙头股公式的股票的股票进行 因子回测 ,用不同的深度机器学习
4 对不同的因子: 强度得分, 日强度变化,1日均价,3日均价, 5日均价,10日均价,20日均价,1日均价,3日均价,5日均价,10日均价,20日均价,volume, money,
5 输出不同的深度机器学习回测结果数据
6.建议的各因子的 最佳组合参数
To address your requests, I'll guide you through the necessary modifications and steps to achieve your goals.
To ensure that only the data under "符合选市场龙头股公式的股票的股票汇总" is outputted, you need to modify the select_stock
function and remove or comment out any sections that output data under "日强度变化大于2.5且强度得分大于6的股票汇总".
Steps:
Locate the select_stock
Function:
Find the function where "符合选市场龙头股公式的股票的股票汇总" is printed. This is already present in your select_stock
function.
Modify the Output: Ensure that only the desired data is printed. Remove or comment out any code that outputs other data.
Example Modification: Remove any print statements or logging that are not related to "符合选市场龙头股公式的股票的股票汇总".
In your after_market_analysis
function, you have code that outputs data under "日强度变化大于2.5且强度得分大于6的股票汇总". To prevent this data from being outputted:
Steps:
Locate the after_market_analysis
Function:
Find the function where this data is being printed.
Remove or Comment Out the Output Code: Delete or comment out the section that outputs the undesired data.
To perform factor backtesting on the selected stocks using deep learning, you need to:
Prepare the Data: Extract the relevant factors for the selected stocks.
Choose Deep Learning Models: Consider models like Artificial Neural Networks (ANN), Long Short-Term Memory networks (LSTM), or Convolutional Neural Networks (CNN) tailored for time-series data.
Implement Backtesting Framework: Use a backtesting framework that integrates with your deep learning models to simulate trading strategies.
Steps:
Data Extraction:
Feature Engineering:
Model Selection:
Training and Validation:
Backtesting:
Hyperparameter Tuning:
The factors you mentioned are:
These factors can be used as features in your models.
Feature Engineering Tips:
After training your models and performing backtesting:
Present Performance Metrics:
Compare Models:
Visualizations:
Based on the backtesting results:
Identify Top Features:
Optimal Factor Combination:
Cross-Validation: Use time-series cross-validation methods to ensure robustness.
Avoid Overfitting: Regularize your models and keep them as simple as possible.
Model Interpretability: Consider using models that provide interpretability to understand the impact of each factor.
Update Your Data Regularly: Ensure that your data is up-to-date, especially since your knowledge cutoff is in 2023.
Risk Management: Always include risk management in your strategies to mitigate potential losses.
Regulatory Compliance: Ensure that your trading activities comply with financial regulations.
By following these steps, you can modify your code to output only the desired data and perform factor backtesting using deep learning methods on the selected stocks. This approach will help you identify the most effective factors and their optimal combinations for your trading strategy.