def parse_base(name='base.ini',root='Base'): ''' 获得基本配置 其中name为配置文件名 root为默认的配置段名 配置文件格式如下: [Base] ;User用于设定连接行情的设定 users = User1,User2,User3 ;Trade用于设定连接交易端的设定 traders = Trader1,Trader2 [User1] port = broker_id = investor_id = passwd = [User2] .... ''' #cfg = ConfigParser.ConfigParser() cfg = CSParser() cfg.read(CONFIG_PATH + name) config = base.BaseObject(users={},traders={}) users = cfg.get(root,'users').split(',') traders = cfg.get(root,'traders').split(',') for user in users: suser = user.strip() if suser == '': continue cuser = base.BaseObject(name = suser) cuser.port = cfg.get(suser,'port') cuser.broker_id = cfg.get(suser,'broker_id') cuser.investor_id = cfg.get(suser,'investor_id') cuser.passwd = cfg.get(suser,'passwd') config.users[user] = cuser for trader in traders: strader = trader.strip() if strader == '': continue ctrader = base.BaseObject(name = strader) ctrader.port = cfg.get(strader,'port') ctrader.broker_id = cfg.get(strader,'broker_id') ctrader.investor_id = cfg.get(strader,'investor_id') ctrader.passwd = cfg.get(strader,'passwd') config.traders[trader] = ctrader return config
def testv(tickss): #tickss = prepare_data_201107() sresults = [] for capacity in (100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1500, 2000): for llen in range(5, 600, 2): #: #print 'in capacity:%s,llen:%s' % (capacity,llen) results = [] for ticks in tickss: trades = make_trades( lvama_opener(llen=llen, capacity=capacity), long_trailing_stop(), ticks, 2, 4) result = base.BaseObject( instrument=ticks[0].instrument, idate=ticks[0].time / 1000000, isum=sum([trade.profit for trade in trades]), #isum2 = sum([trade.profit for trade in trades[:50]]), ilen=len(trades), ) results.append(result) rsum = sum([result.isum for result in results]) rlen = sum([result.ilen for result in results]) sresults.append((capacity, llen, rsum, rlen)) print 'calced capacity=%s,llen=%s,rlen=%s,rsum=%s' % ( capacity, llen, rlen, rsum) if rlen < 10: print u'break' break return sresults
def create_blank_trade(): return base.BaseObject( xtype=base.EMPTY, open_time=-1, open_tick=-1, open_price=0, open_slippage1=0, open_slippage2=0, close_time=-1, close_tick=-1, close_price=0, close_slippage1=0, close_slippage2=0, profit=0, )
def test2(tickss, opener, closer): ''' >>> results = sticks.test2(tickss,sticks.s123_opener(),sticks.short_trailing_stop()) >>> for result in results:print result.instrument,result.idate,result.isum,result.ilen >>> sum([result.isum for result in results]) >>> len(results) ''' results = [] for ticks in tickss: print 'calc: %s:%04d' % (ticks[0].instrument, ticks[0].time / 1000000) trades = make_trades(opener, closer, ticks, base_unit=2, fee=4) result = base.BaseObject( instrument=ticks[0].instrument, idate=ticks[0].time / 1000000, isum=sum([trade.profit for trade in trades]), #isum2 = sum([trade.profit for trade in trades[:50]]), ilen=len(trades), trades=trades, ) results.append(result) #for result in results:print result.instrument,result.idate,result.isum,result.ilen #sum([result.isum for result in results]) return results
def test2m(): logging.basicConfig( filename="ticks_backtest.log", level=logging.INFO, format= '%(name)s:%(funcName)s:%(lineno)d:%(asctime)s %(levelname)s %(message)s' ) dates = [ 20110914, 20110915, 20110916, 20110919, 20110920, 20110921, 20110922, 20110923, 20110926, 20110927, 20110928, 20110929, 20110930 ] dates2 = [ 20110817, 20110818, 20110819, 20110822, 20110823, 20110824, 20110825, 20110826, 20110829, 20110830, 20110831, 20110901, 20110902, 20110909, 20110913, 20110914 ] results = [] #for idate in dates2: for idate in dates: trades = trade1day(lpeak_opener(), long_trailing_stop(), 'IF1110', idate, fee=4) #trades = trade1day(lpeak_opener(),long_trailing_stop(),'IF1109',idate,fee=4) #trades = trade1day(speak_opener(),short_trailing_stop(),'IF1110',idate,fee=4) #trades = trade1day(speak_opener(),short_trailing_stop(),'IF1109',idate,fee=4) result = base.BaseObject( idate=idate, isum=sum([trade.profit for trade in trades]), isum2=sum([trade.profit for trade in trades[:50]]), ilen=len(trades), trades=trades, ) results.append(result) #for result in results:print result.idate,result.isum,result.ilen return results
def make_trades(opener, closer, ticks, base_unit, fee): ''' opener: 开仓策略 closer: 平仓策略 ticks: tick行情序列 open_skip: 开仓成交滑时,0为当前时间成交,1为延后1 tick,2为延后2 tick. 即以成交时间的价格为成交价 close_skip: 平仓成交滑时. #不设置close_ticks: 因为必须确保平仓,所以close_ticks采用30个tick. 这个是全局设置。 base_unit: tick的基础 返回 trades: 其中每个trade包括 xtype : LONG/SHORT/EMPTY open_time: 开仓时间 open_tick: 开仓点的ticks序号 open_base_price: 发出开仓信号的当前价格 open_price: 开仓价格(-为开多,+为开空) open_slippage1: 开仓滑点1,以下一tick成交 open_slippage2: 开仓滑点2,以下第二tick成交. 不计以第三tick或之后成交的 close_time: 平仓时间 close_tick: 平仓点的ticks序号 close_base_price: 发出平仓信号的当前价格 close_price: 平仓价格 close_slippage1:平仓滑点1, 以下一tick成交 close_slippage2:平仓滑点2,以下第二tick成交 profit: 利润 = open_price + close_price - 0.4(手续费) ''' trades = [] cur_trade = create_blank_trade() env = base.BaseObject(pdetail=[], psum=0) #记录关于累计成交的信息,以及划点过线的数据 cur_trade.env = env i = 0 for tick in ticks[:-5]: #最后5秒不开仓 if cur_trade.open_tick > i: #开仓时间在后面 i += 1 continue if cur_trade.xtype != base.EMPTY and closer.check(tick, cur_trade) > 0: #平仓 cur_trade.close_time = tick.time cur_trade.close_tick = i if cur_trade.xtype == base.LONG: cur_trade.close_price1 = ticks[i + 1].price cur_trade.close_price2 = ticks[i + 2].price base_price = tick.price else: cur_trade.close_price1 = -ticks[i + 1].price cur_trade.close_price2 = -ticks[i + 2].price base_price = -tick.price cur_trade.close_base_price = base_price cur_trade.close_price = cur_trade.close_price1 #以下一秒成交为准 cur_trade.close_slippage1 = cur_trade.close_price1 - base_price cur_trade.close_slippage2 = cur_trade.close_price2 - base_price cur_trade.profit = cur_trade.open_price + cur_trade.close_price - fee trades.append(cur_trade) env.psum += cur_trade.profit env.pdetail.append(cur_trade.profit) cur_trade = create_blank_trade() cur_trade.env = env opener.tick(tick) #print 'tick.time=%s,cur_trade.xtype=%s,cur_trade.open_time=%s' % (tick.time,cur_trade.xtype,cur_trade.open_time) if cur_trade.xtype == base.EMPTY and tick.min1 < 1514 and opener.check( cur_trade) > 0: #未开仓时才测试是否要开仓 target_price = tick.price + opener.open_ticks * base_unit if opener.xtype == base.LONG else tick.price - opener.open_ticks * base_unit j = -1 xprice = 0 for jt in ticks[i + 1:i + opener.open_length + 1]: j += 1 if opener.xtype == base.LONG and jt.price <= target_price or opener.xtype == base.SHORT and jt.price >= target_price: xprice = jt.price break if xprice == 0: #未找到 #print u'不能成交,time=%s,cur_price=%s,target_price=%s,sprice=%s' % (tick.time,tick.price,target_price,[(t.price,t.time) for t in ticks[i+1:i+opener.open_length+1]]) continue cur_trade.xtype = opener.xtype cur_trade.open_base_price = -tick.price if opener.xtype == base.LONG else tick.price cur_trade.open_time = jt.time cur_trade.open_tick = i + 1 + j cur_trade.open_price = -jt.price if opener.xtype == base.LONG else jt.price open_price1 = first_price(opener.xtype, target_price, ticks[i + 2:i + opener.open_length + 2]) open_price2 = first_price(opener.xtype, target_price, ticks[i + 3:i + opener.open_length + 3]) cur_trade.open_slippage1 = open_price1 - cur_trade.open_price if open_price1 != 0 else MAX_SLIPPAGE cur_trade.open_slippage2 = open_price2 - cur_trade.open_price if open_price2 != 0 else MAX_SLIPPAGE i += 1 return trades
def parse_strategy(name='strategy.ini',root='strategy'): ''' 获得策略配置 策略配置包括两方面内容: 1. 保存行情的设置, 其中[Trace_Instruments]为合约类设置 [Trace_Instruments] traces = IF,ru,fu,zn,rb,pb,m,a,c,y,b,l,p,v,SR,CF,TA,WS,RO,ER,WT ;a/al/au重复,c/cu重复 ;traces = IF,ru,fu,cu,al,zn,au,rb,pb,m,a,c,y,b,l,p,v,SR,CF,TA,WS,RO,ER,WT ;[Trace_Instruments_Raw]为绝对设置 [Trace_Instruments_Raw] IFs = IF1104,IF1105,IF1106,IF1109 CFs = CF109,CF107 2. 交易策略定制 (todo:将来考虑自动判断主力合约) [Alias_Def] IF_main = IF1105 CF_main = CF109 ;TODO:确定main之后,计算next,third,fourth,分别表示次合约、第三合约、第四合约. 找到主力合约后,按字母序确定 [Trade_Config] ;如果策略文件为strategy,则可以不写 ;strategy_file = strategy traces = IF_main,CF_main [IF_main] max_volume = 2 strategys = IF_A,IF_B,IF_C [IF_A] max_holding = 2 open_volume = 1 opener = day_long_break closer = datr_long_stoper [IF_B] ... ''' #cfg = ConfigParser.ConfigParser() print name cfg = CSParser() cfg.read(CONFIG_PATH + name) config = base.BaseObject(traces=set([]),traces_raw=set([])) ##基于type的合约 ts = cfg.get('Trace_Instruments','traces') for t in ts.split(','): st = t.strip() if st == '': continue config.traces.add(st) ##基于直接硬编码的合约 trs = cfg.items('Trace_Instruments_Raw') tvs = reduce(operator.add,[tv.split(',') for to,tv in trs]) for tv in tvs: stv = tv.strip() if stv == '': continue config.traces_raw.add(stv) ##Instrument别名定义 alias = dict(cfg.items('Alias_Def')) trace_instruments = cfg.get('Trade_Config','traces').split(',') if cfg.has_option('Trade_Config','strategy_file'):#导入策略文件 sfile = cfg.get('Trade_Config','strategy_file') smod = __import__(sfile) mms = sfile.split('.') for mm in mms[1:]: #找到最终的那个模块,__import__返回的是顶级模块 smod = smod.__dict__[mm] else: smod = strategy #print smod.__dict__.keys() config.smodule = smod config.strategy = {} for ti in trace_instruments: sti = ti.strip() if sti == '': continue cs = base.BaseObject(name=alias[sti]) cs.max_volume = int(cfg.get(sti,'max_volume')) cs.max_vtimes = int(cfg.get(sti,'max_vtimes')) cs.max_lost = int(cfg.get(sti,'max_lost')) cs.strategys = [] for scs in cfg.get(sti,'strategys').split(','): sscs = scs.strip() if sscs == '': continue print sscs #current_strategy = base.BaseObject(name=sscs) #current_strategy.max_holding = int(cfg.get(sscs,'max_holding')) #current_strategy.open_volume = int(cfg.get(sscs,'open_volume')) #current_strategy.opener = smod.__dict__[cfg.get(sscs,'opener').strip()]() #需要实例化 #current_strategy.closer = smod.__dict__[cfg.get(sscs,'closer').strip()] current_strategy = strategy.STRATEGY(name = sscs, opener = smod.__dict__[cfg.get(sscs,'opener').strip()], #closer = smod.__dict__[cfg.get(sscs,'closer').strip()], closers = [smod.__dict__[sc.strip()] for sc in cfg.get(sscs,'closers').split(',') if sc.strip()!=''], max_holding = int(cfg.get(sscs,'max_holding')), open_volume = int(cfg.get(sscs,'open_volume')), ) cs.strategys.append(current_strategy) config.strategy[sti] = cs return config
def parse_state(strategy_cfg,instruments,name='state.ini',root='State'): '''现场恢复 ; [State] last_update = 20110401 ;holdings = IF1105,CF109 holdings = IF1105,CF109 [IF1105] instrument = IF1105 opened_volume = 5 opened_orders = IF1105_O1,IF1105_O2 [IF1105_O1] name = IF_A volume = 3 strategy = IF_A ;opener = day_long_break stoper = datr_long_stoper_12 base_price = 32000 current_stop_price = 31930 ;target_price = 0 [IF1105_O2] name = IF_B volume = 1 strategy = IF_A ;opener = day_short_break stoper = datr_short_stoper_12 base_price = 32500 current_stop_price = 32570 ;target_price = 0 [CF109] instrument = CF109 opened_volume = 0 opened_orders = ''' cfg = CSParser() cfg.read(CONFIG_PATH + name) state = base.BaseObject(last_update = int(cfg.get(root,'last_update').strip())) state.holdings = {} holdings = cfg.get(root,'holdings') for hd in holdings.split(','): shd = hd.strip() if shd == '': continue chd = base.BaseObject(name=shd) chd.instrument = cfg.get(shd,'instrument').strip() state.holdings[chd.instrument] = chd ## chd.opened_volume = int(cfg.get(shd,'opened_volume')) chd.orders = [] oos = cfg.get(shd,'opened_orders').split(',') cur_inst = instruments[chd.instrument] for oo in oos: soo = oo.strip() if soo == '': continue order = base.BaseObject(instrument=chd.instrument) order.volume = int(cfg.get(soo,'volume')) order.strategy_name = cfg.get(soo,'strategy_name') #order.opener = strategy_cfg.smodule.__dict__[cfg.get(soo,'opener').strip()] #仅用于判断strategy #order.stoper_class = strategy_cfg.smodule.__dict__[cfg.get(soo,'stoper').strip()] #order.stoper = strategy_cfg.smodule.__dict__[cfg.get(soo,'stoper').strip()](cur_inst.data,0) #满足签名 #order.stoper.load_parameters(cfg.get(soo,'stoper_parameters').strip()) sps = eval(cfg.get(soo,'stopers')) order.stopers = [] print sps for stoper,sparameter in sps: print stoper.strip() xstoper = strategy_cfg.smodule.__dict__[stoper.strip()](cur_inst.data,0) xstoper.load_parameters(sparameter) order.stopers.append(xstoper) #state.mys = cfg.get(soo,'stoper_parameters').strip() #调试用 #print cfg.get(soo,'stoper_parameters').strip() order.base_price = int(cfg.get(soo,'base_price').strip()) order.mytime = int(cfg.get(soo,'mytime').strip()) order.action_type = int(cfg.get(soo,'action_type').strip()) #order.stoper.set_cur_stop(int(cfg.get(soo,'current_stop_price').strip())) if cfg.has_option(soo,'target_price'): order.target_price = int(cfg.get(soo,'target_price')) else: order.target_price = 0 chd.orders.append(order) #print chd.instrument return state
def conv_xslice(mslice): xslice = base.BaseObject(open=mslice.xopen, high=mslice.xhigh, low=mslice.xlow, close=mslice.xclose) return xslice