打工才能致富

策略分享
标签: #<Tag:0x00007f8c5ea57b10>

(itimor) #1
克隆策略
In [15]:
# 加载数据
start_date = '2020-08-10'
end_date = '2020-11-20'
instrument = D.instruments(start_date=start_date, end_date=end_date)
df =D.history_data(instrument, start_date, end_date, ['list_date', 'open', 'close', 'amount', 'high', 'low', 'price_limit_status','st_status','adjust_factor'])

# 通过financial获取财务指标:
financial = D.features(instrument, start_date, end_date, ['fs_operating_revenue_ttm_0', 'fs_current_assets_0', 'fs_non_current_assets_0'])
# 总资产=流动资产+非流动资产:
financial['total_assets'] = financial['fs_current_assets_0'] + financial['fs_non_current_assets_0']
# 资产周转率=营业收入/总资产:
financial['asset_turnover'] = financial['fs_operating_revenue_ttm_0'] / financial['total_assets']
financial_data = financial[['date', 'instrument', 'asset_turnover']]
# 两个DataFrame:历史数据、财务数据 合并:
df = df.merge(financial_data, on=['date', 'instrument'], how='outer')
        
bm = D.history_data(['000300.SHA'],start_date,end_date,['close']) 
bm['ma120_0'] = bm['close'].rolling(120).mean()  # 120日均线值
bm['ma120_min250'] = bm['ma120_0'].rolling(250).min() # 120日均线在250天以内的最低值
bm['var_range'] = bm['close']/bm['ma120_min250']  > 1.75
In [16]:
# 判断是否为一字涨停的函数
def judge_yizizhangting(df):
    if df['price_limit_status']==3 and df['high'] == df['low']:
        return True
    else:
        return False
In [17]:
def handle(df):
    df['highest_60'] = df['high'].rolling(23).max() # 计算60天最高点
    df['ma3_cross_ma5'] = df['close'].rolling(3).mean() - df['close'].rolling(5).mean() # 3日均线上穿5日均线
    df['ma5_cross_ma10'] = df['close'].rolling(5).mean() - df['close'].rolling(10).mean() > 0 # 5日均线上穿10日均线
    df['amount_cond'] = df['amount'] / df['amount'].shift(1) # 当日成交量是前一日的倍数
    df['true_price'] = df['close']/df['adjust_factor'] # 真实价格(后复权价格/复权因子)
    df['list_days'] = (df['date']-df['list_date']).map(lambda x:x.days) # 上市天数
    prices = df['true_price'].map(numpy.float)
    macd, signal, hist = talib.MACD(numpy.array(prices), 12, 26, 9)  # 计算macd各个指标
    # 该列是布尔型变量,表明是否是60日最高点
    df['is_highest'] = df['close'] == df['highest_60'] # 是60日最高点
    df['hist_is_red'] = hist # macd在红色区域
    df['yesterday_status'] = df['price_limit_status'].shift(1) # 昨日涨停状态
    df['today_open_range'] = df['open']/df['close'].shift(1)-1  # 今天开盘跳开幅度
    df['yizizhangting_0'] = df.apply(judge_yizizhangting, axis=1) # 今日是否一字涨停
    df['cw_asset_turnover'] = df['asset_turnover'] > 0.4 # 资产周转率大于0.4
    return df
  
managed_df = df.groupby('instrument').apply(handle).reset_index()
result_buy = managed_df[
    (managed_df['yesterday_status'] != 3)&
    (managed_df['true_price'] < 28)&
    (managed_df['list_days'] > 20)&
    #(managed_df['yizizhangting_0'] != 3)&
    #(managed_df['today_open_range'] <= 0.06)&
    (managed_df['highest_60'])&
    (managed_df['ma3_cross_ma5'] > 0)&
    (managed_df['ma5_cross_ma10'] > 0)&
    (managed_df['amount_cond'] > 0.7)&
    (managed_df['amount_cond'] < 1.8)&
    (managed_df['is_highest'])&   
    (managed_df['cw_asset_turnover'])&
    (managed_df['hist_is_red'] > 0)
                   ]
In [18]:
stock_to_buy = result_buy.groupby('date').apply(lambda df:list(df.instrument)).reset_index().rename(columns={0:'stocks'})
In [19]:
# 选出来的股票还需进行排序
# stocks_sorted = [] 
# for i in range(len(stock_to_buy)):
#     cell = stock_to_buy.ix[i] 
#     date = str(cell.date.date())
#     st = cell.stocks
#     tmp = D.features(st,date,date,['turn_0','market_cap_0','fs_eps_0'])
#     tmp.sort_values(by=['turn_0','market_cap_0','fs_eps_0'],ascending=[0,1,0],inplace=True) # 按照换手率降序排序、市值升序排序、每股收益降序排序
#     stocks_sorted.append(list(tmp.instrument))
# stock_to_buy['stocks_sorted'] = stocks_sorted
In [20]:
stock_to_buy['date'] = stock_to_buy.date.apply(lambda x:x.strftime("%Y-%m-%d"))
stock_to_buy_dic = stock_to_buy.set_index('date').to_dict()['stocks']
def sort_stock(x, stock_to_buy_dic):
    dt = x
    st = stock_to_buy_dic[x]
    tmp = D.features(st,dt,dt,['turn_0','market_cap_0','fs_eps_0'])
    tmp.sort_values(by=['turn_0','market_cap_0','fs_eps_0'],ascending=[0,1,0],inplace=True) # 按照换手率降序排序、市值升序排序、每股收益降序排序
    return list(tmp.instrument)

# 选出来的股票还需进行排序
stock_to_buy_sorted = {i: sort_stock(i, stock_to_buy_dic) for i in stock_to_buy_dic.keys()}
In [21]:
def initialize(context):
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5)) # 设置手续费
    context.hold_days = dict() # 便于记录持仓天数
    context.hold_num = 0  # 持仓股数
    context.max_hold = 10  # 最大持股数量

def handle_data(context, data):
    dt = data.current_dt.strftime('%Y-%m-%d') # 日期
    bm_cond = context.options['bm'].ix[dt]['var_range']
    
    stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  # 持股列表
    context.hold_num = len(stock_hold_now)
    
    # 市场达到清空条件
    if bm_cond:
        for i in stock_hold_now:
            sid = context.symbol(i)
            if data.can_trade(sid):
                order_target_percent(sid, 0)
                
    # 买入的股票列表获取
    try:
        buy = context.options['stock_to_buy_sorted'][dt] 
    except KeyError as e:
        buy = []
    weight = 1 / context.max_hold  # 先采取固定比例 
 
   
    # 达到买入条件就买入
    if len(buy) >= context.max_hold:
        buy = buy[:context.max_hold]
    
    count_buy_num = 0
    for st in buy:
        if context.hold_num >= context.max_hold:
            #print(dt, '已经有五只股票了','分别是: ', stock_hold_now)
            break
            
        if  count_buy_num >= context.max_hold - context.hold_num:
            #print(dt,'已经买完额度')
            break
        sid = context.symbol(st)
        cur_position = context.portfolio.positions[sid].amount
        if cur_position == 0 and data.can_trade(sid):
            order_target_percent(sid, weight)
            count_buy_num += 1 # 每买一只股票就计数
            context.hold_days[st] = context.trading_day_index     # 记录买入时间
 

    # 亏损4%就卖出
    for st in stock_hold_now:
        sid = context.symbol(st)
        cur_position = context.portfolio.positions[sid].amount
        price = data.current(sid, 'price')
        cost = context.portfolio.positions[sid].cost_basis
        
        if price/cost<0.96  and data.can_trade(sid):
            order_target_percent(sid, 0)
            #print(dt, sid ,'止损卖出')
                
    print('当日运行日期',dt)     
    print('明日购买股票',buy) 
               
# 执行回测          
m = M.trade.v2( 
    instruments=instrument,
    start_date=start_date,
    end_date=end_date,
    initialize=initialize,
    handle_data=handle_data,
    order_price_field_buy='open',
    order_price_field_sell='open',
    capital_base=500000,
    benchmark='000300.INDX',
    options={'bm':bm.set_index('date'), 'stock_to_buy_sorted':stock_to_buy_sorted}
)
当日运行日期 2020-08-10
当日购买股票 []
当日运行日期 2020-08-11
当日购买股票 []
当日运行日期 2020-08-12
当日购买股票 []
当日运行日期 2020-08-13
当日购买股票 []
当日运行日期 2020-08-14
当日购买股票 []
当日运行日期 2020-08-17
当日购买股票 []
当日运行日期 2020-08-18
当日购买股票 []
当日运行日期 2020-08-19
当日购买股票 []
当日运行日期 2020-08-20
当日购买股票 []
当日运行日期 2020-08-21
当日购买股票 []
当日运行日期 2020-08-24
当日购买股票 []
当日运行日期 2020-08-25
当日购买股票 []
当日运行日期 2020-08-26
当日购买股票 []
当日运行日期 2020-08-27
当日购买股票 []
当日运行日期 2020-08-28
当日购买股票 []
当日运行日期 2020-08-31
当日购买股票 []
当日运行日期 2020-09-01
当日购买股票 []
当日运行日期 2020-09-02
当日购买股票 []
当日运行日期 2020-09-03
当日购买股票 []
当日运行日期 2020-09-04
当日购买股票 []
当日运行日期 2020-09-07
当日购买股票 []
当日运行日期 2020-09-08
当日购买股票 []
当日运行日期 2020-09-09
当日购买股票 []
当日运行日期 2020-09-10
当日购买股票 []
当日运行日期 2020-09-11
当日购买股票 []
当日运行日期 2020-09-14
当日购买股票 []
当日运行日期 2020-09-15
当日购买股票 []
当日运行日期 2020-09-16
当日购买股票 []
当日运行日期 2020-09-17
当日购买股票 []
当日运行日期 2020-09-18
当日购买股票 []
当日运行日期 2020-09-21
当日购买股票 []
当日运行日期 2020-09-22
当日购买股票 []
当日运行日期 2020-09-23
当日购买股票 []
当日运行日期 2020-09-24
当日购买股票 ['002951.SZA']
当日运行日期 2020-09-25
当日购买股票 []
当日运行日期 2020-09-28
当日购买股票 ['002132.SZA', '603637.SHA', '601113.SHA']
当日运行日期 2020-09-29
当日购买股票 []
当日运行日期 2020-09-30
当日购买股票 ['002931.SZA', '600537.SHA']
当日运行日期 2020-10-09
当日购买股票 ['300542.SZA', '000012.SZA', '601231.SHA']
当日运行日期 2020-10-12
当日购买股票 ['300424.SZA', '300062.SZA', '300484.SZA', '300675.SZA', '603063.SHA', '002778.SZA', '002611.SZA', '601231.SHA', '600545.SHA', '601633.SHA']
当日运行日期 2020-10-13
当日购买股票 ['300797.SZA', '002576.SZA', '000880.SZA', '600363.SHA', '603380.SHA', '002765.SZA', '600166.SHA', '000625.SZA', '600306.SHA']
当日运行日期 2020-10-14
当日购买股票 ['300547.SZA', '002593.SZA', '002487.SZA', '002531.SZA', '002026.SZA', '600203.SHA', '000157.SZA']
当日运行日期 2020-10-15
当日购买股票 ['002087.SZA', '300421.SZA', '002662.SZA', '601208.SHA', '600470.SHA']
当日运行日期 2020-10-16
当日购买股票 ['300797.SZA', '300335.SZA', '300402.SZA']
当日运行日期 2020-10-19
当日购买股票 ['300727.SZA', '002884.SZA', '603703.SHA', '600470.SHA', '600785.SHA']
当日运行日期 2020-10-20
当日购买股票 ['300112.SZA', '603919.SHA']
当日运行日期 2020-10-21
当日购买股票 ['002789.SZA', '600667.SHA']
当日运行日期 2020-10-22
当日购买股票 ['300269.SZA', '600419.SHA']
当日运行日期 2020-10-23
当日购买股票 []
当日运行日期 2020-10-26
当日购买股票 ['300062.SZA', '300444.SZA', '603050.SHA', '603667.SHA']
当日运行日期 2020-10-27
当日购买股票 ['300549.SZA']
当日运行日期 2020-10-28
当日购买股票 ['300647.SZA', '300221.SZA', '002444.SZA']
当日运行日期 2020-10-29
当日购买股票 ['300469.SZA', '300605.SZA', '600399.SHA', '002290.SZA']
当日运行日期 2020-10-30
当日购买股票 ['002280.SZA']
当日运行日期 2020-11-02
当日购买股票 ['000985.SZA', '300514.SZA', '600006.SHA', '300790.SZA', '002444.SZA', '603198.SHA']
当日运行日期 2020-11-03
当日购买股票 ['300283.SZA', '002524.SZA', '600028.SHA']
当日运行日期 2020-11-04
当日购买股票 ['300227.SZA', '600418.SHA', '300432.SZA', '600686.SHA', '002435.SZA']
当日运行日期 2020-11-05
当日购买股票 ['002240.SZA', '600006.SHA', '600148.SHA', '603277.SHA']
当日运行日期 2020-11-06
当日购买股票 []
当日运行日期 2020-11-09
当日购买股票 ['300565.SZA', '605158.SHA', '000039.SZA', '000829.SZA', '601598.SHA', '000807.SZA', '601168.SHA', '601919.SHA', '002455.SZA', '002789.SZA']
当日运行日期 2020-11-10
当日购买股票 ['600220.SHA', '600255.SHA', '000923.SZA', '600691.SHA']
当日运行日期 2020-11-11
当日购买股票 []
当日运行日期 2020-11-12
当日购买股票 ['300019.SZA', '600559.SHA', '600596.SHA', '600197.SHA', '000923.SZA', '002290.SZA', '000635.SZA', '002075.SZA']
当日运行日期 2020-11-13
当日购买股票 ['002149.SZA', '000635.SZA', '002096.SZA', '000626.SZA']
当日运行日期 2020-11-16
当日购买股票 ['600336.SHA', '000807.SZA', '002149.SZA', '600449.SHA', '000923.SZA', '603648.SHA', '002906.SZA', '600022.SHA', '603223.SHA', '600853.SHA']
当日运行日期 2020-11-17
当日购买股票 ['605333.SHA', '002553.SZA', '002760.SZA', '601919.SHA', '600507.SHA', '600255.SHA']
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: an integer is required

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: '2020-11-18'

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
TypeError: an integer is required

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: '2020-11-18'

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: 1605657600000000000

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: Timestamp('2020-11-18 00:00:00')

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: 1605657600000000000

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
KeyError: Timestamp('2020-11-18 00:00:00')

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
<ipython-input-21-e0c404526c97> in <module>()
     73     capital_base=500000,
     74     benchmark='000300.INDX',
---> 75     options={'bm':bm.set_index('date'), 'stock_to_buy_sorted':stock_to_buy_sorted}
     76 )

<ipython-input-21-e0c404526c97> in handle_data(context, data)
      7 def handle_data(context, data):
      8     dt = data.current_dt.strftime('%Y-%m-%d') # 日期
----> 9     bm_cond = context.options['bm'].ix[dt]['var_range']
     10 
     11     stock_hold_now = [equity.symbol for equity in context.portfolio.positions]  # 持股列表

KeyError: '2020-11-18'