| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- # 克隆自聚宽文章: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
|