# 克隆自聚宽文章:https://www.joinquant.com/post/52938 # 标题:QDII ETF/LOF 折溢价策略 # 作者:Gyro^.^ # 实际地址:https://www.joinquant.com/algorithm/index/edit?algorithmId=9608e6e01e60c8b9c1e0d8521b10882d import pandas as pd import datetime as dt from jqdata import * def initialize(context): # setting system log.set_level('order', 'error') set_option('use_real_price', True) set_option('avoid_future_data', True) # setting strategy run_daily(iUpdate, 'before_open') run_daily(iTrader, 'every_bar') run_daily(iReport, 'after_close') def iUpdate(context): # parameters keys = ['标普', '美国', '纳指', '纳斯达克', '法国', '德国', \ '日经', '亚太', '东南亚', '印度', '沙特',] black_list = ['562060.XSHG'] # all funds dt_last = context.previous_date all_fund = get_all_securities('fund', dt_last) # onlist 1-month dt_1m = dt_last - dt.timedelta(days=30) funds = all_fund[all_fund.start_date < dt_1m].index.tolist() # filter, liquity hm = history(20, '1d', 'money', funds).mean() funds = hm[hm > 1e6].index.tolist() # key funds funds = [s for k in keys for s in funds if k in all_fund.display_name[s]] # black_list funds = [s for s in funds if s not in black_list] # net value value = get_extras('unit_net_value', funds, end_date=dt_last, count=2).iloc[0] # price price = history(1, '1d', 'close', funds).iloc[0] # low price r = price/value - 1.0 r = r[r < 0.15].sort_values() # choice funds g.ratio = r log.info('funds', len(g.ratio)) def iTrader(context): # load data r = g.ratio position_size = 1.0/max(3, len(g.ratio)) * context.portfolio.total_value lm_value = 0.8*position_size hm_value = 1.3*position_size cash_size = 0.1 * context.portfolio.total_value cdata = get_current_data() # sell for s in context.portfolio.positions: if cdata[s].paused: continue if s not in r.index: log.info('sell', s, cdata[s].name) order_target(s, 0, MarketOrderStyle(0.99*cdata[s].last_price)) # buy stocks for s in r.index: if context.portfolio.available_cash < cash_size: break if cdata[s].paused: continue if s not in context.portfolio.positions: if r[s] < 0: log.info('buy', s, cdata[s].name) order_target_value(s, position_size, MarketOrderStyle(1.01*cdata[s].last_price)) elif context.portfolio.positions[s].value < lm_value: if r[s] < 0: log.info('balance+', s, cdata[s].name) order_target_value(s, position_size, MarketOrderStyle(1.01*cdata[s].last_price)) elif context.portfolio.positions[s].value > hm_value: if r[s] > 0: log.info('balance-', s, cdata[s].name) order_target_value(s, position_size, MarketOrderStyle(0.99*cdata[s].last_price)) def iReport(context): # load data cdata = get_current_data() tvalue = context.portfolio.total_value # table of positions ptable = pd.DataFrame(columns=['amount', 'value', 'weight', 'name']) for s in context.portfolio.positions: ps = context.portfolio.positions[s] ptable.loc[s] = [ps.total_amount, int(ps.value), 100*ps.value/tvalue, cdata[s].name] ptable = ptable.sort_values(by='weight', ascending=False) # daily report pd.set_option('display.max_rows', None) log.info(' positions', len(ptable), '\n', ptable.head(10)) log.info(' total value %.2f, cash %.2f', \ context.portfolio.total_value/10000, context.portfolio.available_cash/10000) # end