1. 程式人生 > >量化交易-簡單市值輪動策略學習

量化交易-簡單市值輪動策略學習

根據個人習慣,對程式碼進行了調整?

策略說明

每隔10個交易日,等金額持有市值排名最小的前5只股票,賣出其他股票

回測和原始碼如下:

def initialize(context):
    g.stocksnum = 5 # 持有最小市值股票數
    g.period = 10 # 輪動頻率
    run_daily(daily,time='every_bar')# 週期迴圈daily
    g.days = 1 # 記錄策略進行到第幾天,初始為1

def daily(context):
    # 判斷策略進行天數是否能被輪動頻率整除餘1
    if g.days % g.period ==
1: # 獲取當前時間 date=context.current_dt.strftime("%Y-%m-%d") # 獲取上證指數和深證綜指的成分股程式碼並連線,即為全A股市場所有股票 scu = get_index_stocks('000001.XSHG')+get_index_stocks('399106.XSHE') # 選出在scu內的股票的股票程式碼,並按照當前時間市值從小到大排序 df = get_fundamentals(query( valuation.code,
valuation.market_cap ).filter( valuation.code.in_(scu) ).order_by( valuation.market_cap.asc() ), date=date ) # 取出前g.stocksnum名的股票程式碼,並轉成list型別,buylist為選中的股票 buylist =list(df['code'][:g.stocksnum]) # 對於每個當下持有的股票進行判斷:現在是否已經不在buylist裡,如果是則賣出
for stock in context.portfolio.positions: if stock not in buylist: #如果stock不在buylist order_target(stock, 0) #調整stock的持倉為0,即賣出 # 將資金分成g.stocksnum份 position_per_stk = context.portfolio.cash/g.stocksnum # 用position_per_stk大小的g.stocksnum份資金去買buylist中的股票 for stock in buylist: order_value(stock, position_per_stk) else: pass # 什麼也不做 g.days = g.days + 1 # 策略經過天數增加1

經過思考?,我認為這個策略可以改進

  • 如果買入列表中的股票有停牌的,不僅無法買入,還會影響資金利用率,所以我講買入列表中的停牌股票剔除掉
  • 資金分配不是按照固定持股數進行等額分配,而是根據經過篩選實際可以買入的數量來分配
  • 如果已經持倉的股票,不會被二次買入
  • 由於經過篩選後,可買入的股票將會變少,在概率上來講是這樣,所以我講持股數量提升為10

改進程式碼如下,包括回測結果

def initialize(context):
    """初始化函式"""
    
    # 持有最小市值股票數
    g.stocksnum = 10 
    # 輪動頻率
    g.period = 10
    # 記錄策略進行到第幾天
    g.days = 0 
    # 週期迴圈daily
    run_daily(daily,time='every_bar')
    

def daily(context):
    """交易函式"""
    
    # 每執行一天加一
    g.days += 1
    # 判斷策略進行天數是否能被輪動頻率整除餘1
    if g.days % g.period != 1:
        return

    # 獲取當前時間
    date=context.current_dt.strftime("%Y-%m-%d")
    # 獲取上證指數和深證綜指的成分股程式碼並連線,即為全A股市場所有股票
    # 這裡股票池不放在全域性中是因為總有新發型股票出現,所以要動態獲取股票池
    scu = get_index_stocks('000001.XSHG') + get_index_stocks('399106.XSHE')

    # 選出在scu內的股票的股票程式碼,並按照當前時間市值從小到大排序
    df = get_fundamentals(query(
            valuation.code,
            valuation.market_cap
        ).filter(
            valuation.code.in_(scu)
        ).order_by(
            valuation.market_cap.asc()
        ), date=date
        )

    # 取出前g.stocksnum名的股票程式碼,並轉成list型別,buylist為選中的股票
    buylist =list(df['code'][:g.stocksnum])

    # 對於每個當下持有的股票進行判斷:現在是否已經不在buylist裡,如果是則賣出
        if stock not in buylist: #如果stock不在buylist
            order_target(stock, 0) #調整stock的持倉為0,即賣出

    # 已經持倉的不會再被買入
    buy_list = list(set(buylist) - set(context.portfolio.positions.keys()))
    # 當日停牌的股票不交易
    current_data = get_current_data()
    buy_list = [stock for stock in buylist if not current_data[stock].paused]
    # 如果沒有需要買進的股票,就返回
    if len(buy_list) <= 0:
        return
    # 動態分配資金
    position_per_stk = context.portfolio.cash/len(buy_list)
    # 動態買入股票
    for stock in buy_list:
        order_value(stock, position_per_stk)
    

經過調整,回測效果提升將近90個百分點。

如果還有改進想法的看官,可以提出建議。另外,小市值策略在近期其實效果很差,與市場整體有關。另外,小市值經常有停牌退市的風險,很有可能在持有階段停牌,所以風險很高