Warning: file_exists(): open_basedir restriction in effect. File(/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-content/db.php) is not within the allowed path(s): (/www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/:/tmp/:/proc/:/var/log/nginx/:/www/wwwroot/com.xiximiao.oa/com.cmstop/public/:/www/wwwroot/com.xiximiao.oa/com.cmstop/vendor/:/www/wwwroot/com.xiximiao.oa/com.cmstop/ppk/) in /www/wwwroot/com.xiximiao.oa/com.cmstop/public/www/wp-includes/load.php on line 707
2336 【菜场大妈】股息率小市值策略,10年206倍,5年10.8倍 » 轻知量化 QMT、PTrade、聚宽策略分享交流平台

2336 【菜场大妈】股息率小市值策略,10年206倍,5年10.8倍


import pandas as pd  # 用于数据处理和分析的库
from jqdata import *  # 聚宽数据API,提供数据获取和交易执行的功能
import redis  # Redis是一个开源的键值存储系统,常用于数据缓存
import json  # 用于处理JSON数据格式

def initialize(context):
    # 设置日志级别为'error',只记录错误信息
    log.set_level('order', 'error')
    # 设置使用真实价格进行交易
    set_option('use_real_price', True)
    # 避免使用未来数据
    set_option('avoid_future_data', True)
    # 设置基准为中证500指数
    set_benchmark('000905.XSHG')
    # 设置滑点为理想情况,纯为了跑分好看,实际使用注释掉为好
    # set_slippage(PriceRelatedSlippage(0.000))
    # 设置交易成本,包括印花税、买卖佣金等
    set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5),type='fund')
    # strategy
    # 策略初始化设置
    # 全局变量设置
    g.no_trading_today_signal = False  # 初始设置今天不交易的信号为False
    g.stock_num = 5  # 设置要持有的股票数量为5
    g.choice = []  # 初始化选择的股票列表
    g.just_sold = []  # 初始化最近卖出的股票列表
    # 设置定时运行的任务
    run_daily(prepare_stock_list, time='9:05', reference_security='000300.XSHG')  # 每个交易日9:05运行prepare_stock_list函数
    run_daily(check_limit_up, time='14:00')  # 每个交易日14:00运行check_limit_up函数检查涨停股
    run_monthly(my_Trader, 1, time='9:30', force=True)  # 每月第一个交易日9:30运行my_Trader函数
    run_monthly(go_Trader, 1, time='14:55', force=True)  # 每月第一个交易日14:55运行go_Trader函数
    run_daily(close_account, '14:30')  # 每个交易日14:30运行close_account函数进行账户结算
    run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')  # 每个交易日收盘后运行after_market_close函数

# 定义函数 my_Trader,用于执行选股和过滤逻辑
def my_Trader(context):
    # 获取前一个交易日的日期
    dt_last = context.previous_date
    # 获取前一个交易日所有上市股票的列表
    stocks = get_all_securities('stock', dt_last).index.tolist()
    # 过滤掉科创板及精选层股票
    stocks = filter_kcbj_stock(stocks)
    # 获取股息率大于0且小于0.25的股票列表
    # False 参数表示股息率升序排列,0 和 0.25 是股息率的筛选范围
    stocks = get_dividend_ratio_filter_list(context, stocks, False, 0, 0.25)
    # 获取PEG(市盈率相对盈利增长比)筛选后的股票列表
    stocks = get_peg(context, stocks)
    # 过滤掉ST股票
    choice = filter_st_stock(stocks)
    # 过滤掉停牌的股票
    choice = filter_paused_stock(choice)
    # 过滤掉涨停的股票
    choice = filter_limitup_stock(context, choice)
    # 过滤掉跌停的股票
    choice = filter_limitdown_stock(context, choice)
    # 过滤掉高价股,此处假设函数 filter_highprice_stock 存在并可用
    choice = filter_highprice_stock(context, choice)
    # 选择最终的候选股票列表,并截取前 g.stock_num 个作为最终选择
    g.choice = choice[:g.stock_num]

# 定义函数 go_Trader,用于执行月度调仓逻辑
def go_Trader(context):
    # 检查是否设置了今日不交易的信号,如果没设置,则执行交易逻辑
    if g.no_trading_today_signal == False:
        # 每月清零一次 g.just_sold,防止其中内容一直膨胀
        g.just_sold = []
        # 获取当前市场的所有数据
        cdata = get_current_data()
        # 获取经过筛选的股票列表
        choice = g.choice

        # 卖出逻辑
        # 遍历当前投资组合中的每一只股票
        for s in context.portfolio.positions:
            # 如果当前股票不在 choice 列表中,则卖出
            if (s not in choice):
                # 记录卖出操作
                log.info('Sell', s, cdata[s].name)
                # 将股票 s 的持仓目标设置为 0,即全部卖出
                order_target(s, 0)
        # 买入逻辑
        # 获取当前投资组合的持仓数量
        position_count = len(context.portfolio.positions)
        # 如果 choice 列表中的股票数量大于当前持仓数量
        if g.stock_num > position_count:
            # 计算每只股票应该买入的金额
            psize = context.portfolio.available_cash / (g.stock_num - position_count)
            # 遍历 choice 列表中的每一只股票
            for s in choice:
                # 如果当前股票不在投资组合的持仓中
                if s not in context.portfolio.positions:
                    # 记录买入操作
                    log.info('buy', s, cdata[s].name)
                    # 下单,买入 psize 金额的股票 s
                    order_value(s, psize)
                    # 如果持仓数量达到了目标持仓数量,则停止买入
                    if len(context.portfolio.positions) == g.stock_num:
                        break

# 定义函数 cap,用于打印持仓股票的市值信息
def cap(context):
    # 获取当前市场的所有数据
    current_data = get_current_data()
    # 获取当前投资组合中持仓的股票列表
    hold_stocks = context.portfolio.positions.keys()
    for s in hold_stocks:
        # 构建查询对象,用于查询指定股票的财务数据
        q = query(valuation).filter(valuation.code == s)
        # 获取该股票的财务数据
        df = get_fundamentals(q)
        # log.info(s,current_data[s].name,'流值',df['circulating_market_cap'][0],'亿')
        log.info(s,current_data[s].name,'市值',df['market_cap'][0],'亿')
        log.info(s,current_data[s].name,'股价',current_data[s].last_price,'元')

关键函数解锁后查看:

  
# 准备股票池
def prepare_stock_list(context):
    #获取已持有列表
    g.high_limit_list = []   
    hold_list = list(context.portfolio.positions)
    if hold_list:
        df = get_price(hold_list, end_date=context.previous_date, frequency='daily',
                       fields=['close', 'high_limit'],
                       count=1, panel=False)
        g.high_limit_list = df[df['close'] == df['high_limit']]['code'].tolist()
    # 判断今天是否为账户资金再平衡的日期,使用 today_is_between 函数判断当前日期是否在 '04-05' 到 '04-30' 之间
    g.no_trading_today_signal = today_is_between(context, '04-01', '04-30')

#  调整昨日涨停股票
def check_limit_up(context):
    if g.no_trading_today_signal == False:   # 检查是否设置了今日不交易的信号,如果没设置,则执行以下逻辑
        position_count = len(context.portfolio.positions)  # 获取当前投资组合的持仓数量
        # 如果目标持仓数量大于当前持仓数量,并且当前持仓数量不为0(避免在第一次运行时抢在 go_Trader 前买入)
        if g.stock_num > position_count and position_count != 0: # position_count != 0 用于避免第一次运行时代替go_trader 买入
            # 调用 my_Trader 函数更新 g.choice 列表,计算需要买入的股票
            my_Trader(context)
            # 获取当前市场的所有数据
            cdata = get_current_data()
            # 计算剩余仓位的现金应该买入每只股票的金额
            psize = context.portfolio.available_cash/(g.stock_num - position_count)
            # 遍历 g.choice 列表中的股票
            for s in g.choice:
                # 如果当前股票不在投资组合的持仓中,并且不在最近卖出的列表中
                if s not in context.portfolio.positions and s not in g.just_sold:
                    # 下单买入这只股票
                    order = order_value(s, psize)
                    # 如果持仓数量达到了目标持仓数量,则停止买入
                    if len(context.portfolio.positions) == g.stock_num:
                        break
        # 获取当前市场的所有数据,用于检查股票价格
        current_data = get_current_data()
        if g.high_limit_list:   # 如果存在昨日涨停的股票列表
            for stock in g.high_limit_list:  # 遍历昨日涨停的股票列表
                # 如果当前股票的最新价格低于涨停价(即没有继续涨停)
                if current_data[stock].last_price < current_data[stock].high_limit:
                    order_target(stock, 0)  # 卖出这只股票,将其持仓目标设置为 0
                    g.just_sold.append(stock)   # 将这只股票添加到最近卖出的列表中

# 过滤科创北交股票
def filter_kcbj_stock(stock_list):
    for stock in stock_list[:]:
        if stock[0] == '4' or stock[0] == '8' or stock[:2] == '68':
            stock_list.remove(stock)
    return stock_list

# 过滤停牌股票
def filter_paused_stock(stock_list):
	current_data = get_current_data()         # 获取当前所有股票的数据
	return [stock for stock in stock_list if not current_data[stock].paused]

# 过滤ST及其他具有退市标签的股票
def filter_st_stock(stock_list):
	current_data = get_current_data()          # 获取当前所有股票的数据
	return [stock for stock in stock_list
			if not current_data[stock].is_st
			and 'ST' not in current_data[stock].name
			and '*' not in current_data[stock].name
			and '退' not in current_data[stock].name]

# 过滤涨幅过大的股票
def filter_limitup_stock(context, stock_list):
	last_prices = history(1, unit='1m', field='close', security_list=stock_list)
	current_data = get_current_data()         # 获取当前所有股票的数据
	
	return [stock for stock in stock_list if stock in context.portfolio.positions.keys()
			or last_prices[stock][-1] < current_data[stock].high_limit*0.97]

# 过滤跌幅过大的股票
def filter_limitdown_stock(context, stock_list):
	last_prices = history(1, unit='1m', field='close', security_list=stock_list)
	current_data = get_current_data()          # 获取当前所有股票的数据
	
	return [stock for stock in stock_list if stock in context.portfolio.positions.keys()
			or last_prices[stock][-1] > current_data[stock].low_limit*1.04]

#2-4 过滤股价高于10元的股票	
def filter_highprice_stock(context,stock_list):
	# 使用 history 函数获取 stock_list 中所有股票的最新(最近一分钟)收盘价
	last_prices = history(1, unit='1m', field='close', security_list=stock_list)
	return [stock for stock in stock_list if stock in context.portfolio.positions.keys()
			or last_prices[stock][-1] < 10]
						
def after_market_close(context):
    log.info(str(context.current_dt))
    
#4-2 清仓后次日资金可转
def close_account(context):
    if g.no_trading_today_signal == True:
        position_count = context.portfolio.positions
        if len(position_count) != 0:
            for stock in position_count:
                position = context.portfolio.positions[stock]
                close_position(position)
                log.info("卖出[%s]" % (stock))

#3-1 交易模块-自定义下单
def order_target_value_(security, value):
    if value == 0:     # 检查目标价值是否为0,即是否需要清仓
        log.debug("Selling out %s" % (security))
    else:
        log.debug("Order %s to value %f" % (security, value))
    return order_target_value(security, value)    # 调用聚宽平台的order_target_value函数执行交易

#3-2 交易模块-开仓
def open_position(security, value):
    order = order_target_value_(security, value)  # 尝试对指定股票进行下单到特定价值
    if order != None and order.filled > 0:        # 检查订单是否创建成功且有成交
        return True  # 开仓成功
    return False  # 开仓失败
                
#3-3 交易模块-平仓
def close_position(position):
    security = position.security  # 获取持仓的股票代码
    order = order_target_value_(security, 0)  # 下单清仓 ;可能会因停牌失败
    if order != None:  # 检查订单是否创建成功
        if order.status == OrderStatus.held and order.filled == order.amount:  # 检查订单状态是否为全部成交且订单数量等于下单数量
            return True  # 平仓成功
    return False  # 平仓失败
    
#4-1 判断今天是否为账户资金再平衡的日期
def today_is_between(context, start_date, end_date):
    today = context.current_dt.strftime('%m-%d')       # 获取当前日期并格式化为月-日格式
    if (start_date <= today) and (today <= end_date):  # 判断当前日期是否在指定的起始和结束日期之间
        return True   # 今天是资金再平衡的日期
    else:
        return False  # 今天不是资金再平衡的日期

2025-02-21
⚠️
本站资源大多来自网络,仅供网友学习交流,未经作者或上传书面授权,请勿作他用。
站长 vx: xiangyin615 或者 留言反馈 ,我们将尽快处理。
Notice: When you of the legal rights be violate, please stir to vx: xiangyin615
个人中心
购物车
优惠劵
搜索