小市值策略-单因子

2024-01-02 08:17:01

小市值策略-单因子

选取115只股票

from jqdata import *
from jqlib.technical_analysis import *
import datetime
from jqfactor import *
import numpy as np
import pandas as pd

#初始化函数 
def initialize(context):
    # 设定基准
    set_benchmark('000905.XSHG')
    # 用真实价格交易
    set_option('use_real_price', True)
    # 打开防未来函数
    set_option("avoid_future_data", True)
    # 将滑点设置为0
    set_slippage(FixedSlippage(0.02))
    # 设置交易成本万分之三,不同滑点影响可在归因分析中查看
    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='stock')
    # 过滤order中低于error级别的日志
    log.set_level('order', 'error')
    #初始化全局变量
    g.no_trading_today_signal = False
    g.stock_num = 115
    g.hold_list = [] #当前持仓的全部股票    
    g.yesterday_HL_list = [] #记录持仓中昨日涨停的股票
    g.target_stock = []

    # 设置交易运行时间
    # 每周第一个交易日运行
    run_weekly(weekly_filter, 1, time='before_open')
    
    run_weekly(get_stock_list, 1, time='9:10')
    
    run_daily(prepare_stock_list, '9:05')
    run_weekly(weekly_adjustment, 1, '9:31')
    run_daily(close_account, '14:30')
    run_daily(print_position_info, '15:10')
    
    g.pools = set()


def weekly_filter(context):
    today = context.current_dt
    yesterday = today -  datetime.timedelta(days=1)
    start_day = today -  datetime.timedelta(days=375)
    yesterday = yesterday.strftime('%Y-%m-%d')
    
    codes = list(g.pools)
    
    
    # 选出小市值的股票
    q = query(
            valuation.code,
            valuation.circulating_market_cap
        ).filter(
            valuation.circulating_market_cap
        ).order_by(
            valuation.circulating_market_cap.asc())
    codes = get_fundamentals(q).code.tolist()
    
    # 筛选出主板、创业板股票
    codes = [code for code in codes if code[:2] in ('60','00','30')]
    log.info("Top 10 小市值:" + str(codes[:10]))
    # 过滤ST股票
    df = get_extras('is_st', codes, end_date=yesterday,count=1)
    df = df.T
    df.columns = ['is_st']
    df=df[df['is_st']==0]
    codes = df.index.tolist()
    # 过滤次新股
    q = query(finance.STK_LIST.code).filter(
        finance.STK_LIST.start_date <= start_day,
        finance.STK_LIST.code.in_(codes)
        )
    codes = list(finance.run_query(q).code)
    g.pools = set(codes)
    
#1-1 准备股票池
def prepare_stock_list(context):

    #获取已持有列表
    g.hold_list= list(context.portfolio.positions.keys())
    #获取昨日涨停列表
    if g.hold_list != []:
        df = get_price(g.hold_list, end_date=context.previous_date, frequency='daily', fields=['close','high_limit'], count=1, panel=False, fill_paused=False)
        df = df[df['close'] == df['high_limit']]
        g.yesterday_HL_list = list(df.code)
    else:
        g.yesterday_HL_list = []
        
    
    #判断今天是否为账户资金再平衡的日期 或者 元旦到春节之间的日期
    # g.no_trading_today_signal = today_is_between(context, '04-05', '04-30')


def get_stock_list(context):
    final_list = set()
    initial_list = list(g.pools)
    if len(initial_list) == 0:
        return []
    initial_list = filter_paused_stock(initial_list)
    initial_list = filter_st_stock(initial_list)
    
    today = context.current_dt
    # 通过timedelta算出前一天的日期
    delta = datetime.timedelta(days=1)
    yesterday = today - delta
    yesterday = yesterday.strftime('%Y-%m-%d')

    q = query(valuation.code, 
        valuation.circulating_market_cap).filter(valuation.code.in_(initial_list)).order_by(
                valuation.circulating_market_cap.asc()).limit(g.stock_num)

    codes = get_fundamentals(q).code.tolist()
    circulating_market_cap_list = get_fundamentals(q).circulating_market_cap.tolist()

    log.info('数据库拉取的股票数量:{}'.format(len(codes)))
    log.info('最小流通市值:{}, 最大流通市值:{}'.format(min(circulating_market_cap_list), max(circulating_market_cap_list)))
        
    final_list = codes.copy()
    print('数据库拉取的股票:{}'.format(final_list))

    final_list = filter_paused_stock(final_list)
    print('过滤停牌后的股票:{}'.format(final_list) )
    final_list = filter_st_stock(final_list)
    g.target_stock  = final_list
    log.info('每周一买入的股票:', final_list)

    message = '需要购买的股票为:\n {}'.format('\n'.join(final_list))
    # send_message(message, channel='weixin')

#1-3 整体调整持仓
def weekly_adjustment(context):
    if g.no_trading_today_signal:
        return

    #获取应买入列表 
    target_list = g.target_stock
    #调仓卖出
    for stock in g.hold_list:
        if (stock not in target_list) and (stock not in g.yesterday_HL_list):
            log.info("卖出[%s]" % (stock))
            order_target(stock, 0)
        else:
            log.info("已持有[%s]" % (stock))
    #调仓买入
    position_count = len(context.portfolio.positions)
    target_num = len(target_list)
    if target_num > position_count:
        value = context.portfolio.cash / (target_num - position_count)
        for stock in target_list:
            if context.portfolio.positions[stock].total_amount == 0:
                if open_position(stock, value):
                    if len(context.portfolio.positions) == target_num:
                        break

文章来源:https://blog.csdn.net/sinat_21250935/article/details/135317927
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。