def getTradeDay(d1, d2, dtype=backtest_runner.BackTestPolicy.enum.hisdat_mode): """确定是交易日 return: (d1, d2)""" try: if dtype == backtest_runner.BackTestPolicy.enum.hisdat_mode: df = stock.getHisdatDataFrameFromRedis(code, d1, d2) else: df = stock.getFenshiDfUseRedis(code, d1,d2) if len(df) == 0: #在指定日期内没有数据,应该是新股或次新股 return d2,d2 d2 = agl.datetime_to_date(df.index[-1]) if agl.DateTimeCmp(d1, agl.datetime_to_date(df.index[0])) <0: d1 = agl.datetime_to_date(df.index[0]) except: pass return d1, d2
def calc_history_syl(df, df_hisdat, period='year', dtype='pd.series'): """计算股票的历史市盈率 df : df 单个股票的净利润表 df_hisdat : 日线 period: str year|quarter dtype: str pd.df|pd.series return: df index如果是年一般指年尾,虽然使用的是2016-1-1, 因此调整为下一年年初""" rows = df[u'基本每股收益元'].sort_index() #df_hisdat = stock.getHisdatDataFrameFromRedis(code) if len(df_hisdat) == 0: return pd.Series([]) rows = rows.ix[df_hisdat.index[0]:df_hisdat.index[-1]] if len(rows) == 0: return rows if str(rows.dtype) != 'float64': rows = rows[rows.map(lambda x: x.strip() != '')] rows = rows.astype(float) for i in range(len(rows)): price = np.nan d = agl.datetime_to_date(rows.index[i]) # d is year if period == 'year': d = d.split('-')[0] try: df_last = df_hisdat[d].sort_index() except: return pd.Series([]) else: df_last = df_hisdat[:d].sort_index() if len(df_last) > 0: price = df_last.iloc[-1]['c'] mgsy = rows.iloc[i] if period == 'quarter': #季度转年度 quarter = df_last.index[-1].quarter mgsy = mgsy / quarter * 4 syl = stock.SYL(price, mgsy) #print i, d, mgsy, price, syl rows.iloc[i] = syl if period == "year": #调整index为下一年的年初 #print rows.index last_next_year = str(int(rows.index[-1].year) + 1) + '-1-1' new_index = rows.index.astype(str).tolist() new_index = new_index[1:] + [last_next_year] rows.index = pd.DatetimeIndex(new_index) #rows.index = map(lambda x: ) if dtype == 'pd.series': return rows df[u'历史市盈率'] = rows return df[[u'历史市盈率', u'净利润万元']]
def _test_fenshi_redis(self): """取一个个股的redis, 看下日期""" end_day = agl.CurDay() start_day = help.MyDate.s_Dec(end_day, -15) code = u'600100' #取一个值 df_fenshi = getFiveMinFenshiFromRedis(code) df_fenshi_day = df_fenshi.resample('D').dropna() self.assertEqual(len(df_fenshi_day), 5) d = agl.datetime_to_date(df_fenshi_day.index[-1]) self.assertEqual(stock.getKlineLastDay(), d) df = stock.LiveData().getFiveMinHisdat(code) print(df)
def initData(self, start_day, end_day): #数据初始化, 生成数据面板 days = (start_day, end_day) hisdat_start_day = help.MyDate.s_Dec(start_day, -100) self.panel_hisdat = stock.DataSources.getHisdatPanl( self.codes, (hisdat_start_day, end_day)) if start_day == '': start_day = hisdat_start_day fenshi_start_day = help.MyDate.s_Dec(start_day, -5) fenshi_days = (fenshi_start_day, help.MyDate.s_Dec(end_day, 1)) if self.mode & self.enum.hisdat_five_mode == self.enum.hisdat_five_mode: self.panel_fiveminHisdat = stock.DataSources.getFiveMinHisdatPanl( self.codes, fenshi_days) if self.mode == BackTestPolicy.enum.tick_mode: self.dict_fenshi = stock.DataSources.getFenshiPanl( self.codes, fenshi_days) else: self.dict_fenshi = None #self.panel_fiveminHisdat = None for policy in self.policys: policy.data.set_datasource(self.panel_hisdat, self.dict_fenshi, \ self.panel_fiveminHisdat) #修正日期 if self.mode & self.enum.hisdat_mode == self.enum.hisdat_mode: if self.mode & self.enum.hisdat_five_mode == self.enum.hisdat_five_mode: df = self.panel_fiveminHisdat[self.codes[0]] else: df = self.panel_hisdat[self.codes[0]] else: df = self.dict_fenshi[self.codes[0]] if len(df) > 0: end_day = agl.datetime_to_date(df.index[-1]) start_day = help.MyDate.s_Dec(start_day, 2) return start_day, end_day
def ShowTradeResult2(pl, bars, signals, zhijin, changwei, signal_dependent_num=0, freq=300, title=''): """绘制策略的交易结果, 交易剔除了非交易时间, 资金未剔除, 因此两者的xtick看起来是不一致的 注意,bars不能有nan,否则画不出箭头 bars: pd.DateFrame 日线等数据集 index为时间 收盘为['c'] signals: pd.DateFrame 信号 包含技术指标 index同bars zhijin: pd.Serias 资金结果 changwei: 当前仓位 signal_dependent_num: 显示signals里的依赖线 freq: 坐标的间隔 """ # Plot two charts to assess trades and equity curve pl.figure #fig = pl.figure() pl.close() fig = pl.gcf() fig.patch.set_facecolor('white') # Set the outer colour to white ax1 = fig.add_subplot(211, ylabel='Price in RMB') if title != '': pl.title(title, fontproperties=getFont()) #思路, 把时间转整数,显示时再把整数转时间字符串 # 为了去除非交易时间, 把index 转换为整数 date_ticks = copy.deepcopy(bars.index) indexs = np.arange(len(bars)) bars.index = indexs signals.index = indexs if len(bars) == len(zhijin): if zhijin is not None: zhijin.index = indexs if changwei is not None: changwei.index = indexs # Plot the AAPL closing price overlaid with the moving averages bars['c'].plot(ax=ax1, color='r', lw=2.) #显示信号产生的依据, 最好是使用固定的值, 比如信号线1-n, range(n) if signal_dependent_num > 0: signals[np.array(range(signal_dependent_num), dtype=str)].plot(ax=ax1, lw=2.) #signals[['short_ma', 'long_ma']].plot(ax=ax1, lw=2.) # Plot the "buy" trades against AAPL ax1.plot(signals.ix[signals.positions == 1.0].index, bars['c'][signals.positions == 1.0], '^', markersize=10, color='m') # Plot the "sell" trades against AAPL ax1.plot(signals.ix[signals.positions == -1.0].index, bars['c'][signals.positions == -1.0], 'v', markersize=10, color='k') # Plot the equity curve in dollars ax2 = fig.add_subplot(212, ylabel='Portfolio value in RMB') if zhijin is not None and len(zhijin) > 1: zhijin.plot(ax=ax2, lw=2.) legends = ['zhijing'] if changwei is not None and len(changwei) > 1: changwei.plot(ax=ax2) legends.append('changwei') ax2.legend(legends) #剔除非交易时间 #freq = 300 ax1.set_xticks(indexs[::freq]) date_ticks = date_ticks.map(lambda x: agl.datetime_to_date(x)) ax1.set_xticklabels(date_ticks[::freq], rotation=45, ha='right') if len(bars) == len(zhijin): ax2.set_xticks(indexs[::freq]) ax2.set_xticklabels(date_ticks[::freq], rotation=45, ha='right') # Plot the figure #fig.show() pl.show() pl.close()
def ExePolicy(self, code): code = agl.unicode_to_utf8(code) live_data = LiveData() df_hisdat = live_data.getHisdat(code) df_fenshi = live_data.getFenshi(code) df_five_hisdat = live_data.getFiveMinHisdat(code) if agl.IsNone(df_five_hisdat): #print code ,'没有5分钟' return if len(df_fenshi) == 0: return if len(df_five_hisdat) < 30: return price = float(agl.FloatToStr(float(df_fenshi.tail(1)['p']))) yclose = df_hisdat.ix[df_hisdat.index[-1]]['c'] zhangfu = stock.ZhangFu(price, yclose) rsi = stock.RSI(df_five_hisdat['c']) #ui.DrawClosesAndVolumes(pl, df_five_hisdat['c'], rsi) upper, middle, lower = stock.TDX_BOLL(df_five_hisdat['c']) #ui.DrawTs(pl, df_five_hisdat['c'],mid=middle, high=upper, low=lower) highs, lows, closes = df_five_hisdat['h'], df_five_hisdat[ 'l'], df_five_hisdat['c'] #atr = stock.ATR(highs, lows, closes) adx = stock.TDX_ADX(highs, lows, closes) closes = np.array(df_hisdat['c']) if help.MyDate(agl.datetime_to_date(df_hisdat.index[-1])).d < \ help.MyDate(agl.CurDay()).d: closes = agl.array_insert(closes, len(closes), price) four = stock.FOUR(closes) #print code, four[-1] self._dict_four[code] = four[-1] #return #ui.DrawClosesAndVolumes(pl, df_five_hisdat['c'], adx) boll_up = (price - upper[-1]) / upper[-1] boll_mid = (price - middle[-1]) / middle[-1] boll_down = (lower[-1] - price) / lower[-1] boll_width = upper[-1] - lower[-1] if abs(zhangfu) > 0.098 or boll_width < 0.01: return if code == '300033': codename = stock.GetCodeName(code) s = 'rsi = %d %s %s' % (rsi[-1], codename, str(price)) print s if (rsi[-1] > 65 or rsi[-1] < 35) and adx[-1] > 60: codename = stock.GetCodeName(code) s = '%s %s' % (codename, str(price)) sign = False #if code in ['300033','510050']: #sign = True #if adx[-1] > 55: #s += ' ADX=%d'%(adx[-1]) #sign = True if boll_up > -0.003: s += ' 越过布林上轨' #sign = True if abs(boll_mid) < 0.003: s += ' 布林中轨' #sign = True if boll_down > -0.003: s += ' 越过布林下轨' sign = True if four[-1] > 0.1: sign = False #sign = False if sign: #ui.DrawTs(pl, df_five_hisdat['c'],mid=middle, high=upper, low=lower) sInfo = self.calcInfo(code, price, zhangfu) help.myprint(s, sInfo) help.myprint( '[%s,%s] %.3f,%.3f,%.3f,%.2f, four=%.2f, adx=%.2f' % (code, stock.GetCodeName(code), boll_up, boll_mid, boll_down, boll_width, four[-1], adx[-1])) self.NotifyAutoxdShow(code) self.Speak(s)
def _Report(self, policy, start_day, end_day): policy._getAccount().Report(end_day, True) #绘制图形 if hasattr(policy, 'Report'): policy.Report() #end_day = help.MyDate.s_Dec(end_day, 1) #bars = stock.CreateFenshiPd(self.code, start_day, end_day) if self.mode == 0: bars = self.dict_fenshi[self.codes[0]] if len(bars) == 0: return bars = bars.resample('1min').mean() bars['c'] = bars['p'] else: #日线 bars = self.panel_hisdat[self.codes[0]] if self.mode & self.enum.hisdat_five_mode == self.enum.hisdat_five_mode: bars = self.panel_fiveminHisdat[self.codes[0]] bars['positions'] = 0 bars = bars.dropna() df = policy._getAccount().ChengJiao() df_zhijing = policy._getAccount().ZhiJing() init_money = df_zhijing.iloc[0]['资产'] df_zhijing = df_zhijing[bars.index[0]:] df_changwei = policy._getAccount().ChengJiao() cols = ['买卖标志', '委托数量'] df_flag = df_changwei[cols[0]].map(lambda x: x == '证券卖出' and -1 or 1) df_changwei[cols[1]] *= df_flag changwei = df_changwei[cols[1]].cumsum() if self.mode == 1: df.index = df.index.map(lambda x: agl.datetime_to_date(x)) bars.is_copy = False for i in range(len(df)): index = df.index[i] bSell = bool(df.iloc[i]['买卖标志'] == '证券卖出') if index in bars.index: bars.at[index, 'positions'] = agl.where(bSell, -1, 1) #同步资金到bar df_zhijing.is_copy = False df_zhijing['changwei'] = changwei if self.mode == 1: df_zhijing.index = df_zhijing.index.map( lambda x: agl.datetime_to_date(x)) bars = bars.join(df_zhijing) bars = bars.fillna(method='pad') #同步价格的动态总资产 bars['资产'] = bars['可用'] + bars['changwei'] * bars['c'] zhican = (bars['资产'] - init_money) / init_money * 100 zhican = zhican.fillna(0) title = '%s %s' % (self.codes[0], stock.GetCodeName( self.codes[0]).decode('utf8')) ui.TradeResult_Boll(agl.where(policy.pl, policy.pl, pl), bars, \ stock.GuiYiHua(zhican),\ stock.GuiYiHua(bars['changwei']), title=title) if policy.pl is not None: if policy.pl.explicit: #有成交才发布 if len(df) > 0: policy.pl.publish()
def Run(self): account = self._getAccount() code = self.data.get_code() hisdat = self.data.get_hisdat(code) hisdat = hisdat.dropna() closes = hisdat['c'].dropna() if len(closes)<60: return #基本面计算 date = agl.datetime_to_date(self.getCurTime()) history_quarter_syl = jbm.calc_history_syl(self.df_jll, hisdat, 'quarter') syl = history_quarter_syl.ix[:date].iloc[-1] self.jbm = history_quarter_syl #计算技术指标 four = stock.FOUR(closes) boll_up, boll_mid, boll_low ,boll_w= stock.TDX_BOLL2(closes) adx = stock.TDX_ADX(hisdat['h'], hisdat['l'], closes) #收集使用过的技术指标,为了报告使用 self.tech = closes, four, boll_up, boll_mid, boll_low ,boll_w, adx four = four[-1] price = hisdat.iloc[-1]['c'] #print self.getCurTime(), four, price, boll_low[-1], boll_w[-1] #基于价值回归及成本控制,加上技术指标择时 #缺点, 资金利用率低, 选股必须选好, 否则碰到一直下跌的情况就会造成亏损 #优点, 成本在相对安全区域 #当成本亏base_ratio%时加倍买入 df_stock_list = account.StockList() df_stock_list = df_stock_list[df_stock_list['证券代码'] == code] #第一次买 if so.assemble(four<self.base_four[0] ,len(df_stock_list) == 0 , adx[-1] > 60, #price<boll_low[-1] , #boll_w[-1]>2, #syl < 50, ): if hasattr(self, 'base_num_ratio'): total_money = ac.AccountMgr(self._getAccount(), price, code).init_money() self.base_num = ac.ShouShu(total_money*self.base_num_ratio/price) self._getAccount().Order(0, code, price, self.base_num) if len(df_stock_list) > 0: chengben = float(df_stock_list['参考盈亏成本价'].loc[0]) changwei = int(df_stock_list['库存数量'].loc[0]) yinkui = calcYinKui(price, chengben) #agl.Print( '盈亏:', chengben, yinkui, changwei, '频繁') if price < chengben*(1-self.base_ratio): #如果仓位大于总资金的70%, 那么仓位为剩余资金的一半 df_zhijing = account.ZhiJing() canuse_money = float(df_zhijing['可用'][-1]) total_money = canuse_money + changwei*price if canuse_money/total_money<self.base_rhombus_mid_ratio: num = ac.ShouShu(canuse_money/2/price) #这里开始就按上次交易的价格来作为判断, 最后一个买入 df_chengjiao = account.ChengJiao() df_chengjiao = df_chengjiao[df_chengjiao['买0卖1'] == '0'] last_buy_price = float(df_chengjiao['成交价格'][-1]) if price > last_buy_price*(1-self.base_ratio): num = 0 else: num = changwei*self.base_pramid_ratio if num>0: account.Order(0, code, price, num) #当赚base_ratio%时加倍卖出 chengben = float(df_stock_list['买入均价'].loc[0]) sell_avg_price = myredis.createRedisVal(self.key_sell_avg_price, chengben) sell_num = myredis.createRedisVal(self.key_sell_num, 0) if price>chengben*(1+self.base_ratio) and four>self.base_four[1]: #第一次卖 if sell_num.get() == 0: account.Order(1, code, price, self.base_num) sell_avg_price.set(price) sell_num.set(self.base_num) #print '--',chengben, sell_avg_price.get()*(1+self.base_ratio) if price > sell_avg_price.get()*(1+self.base_ratio): num = int(df_stock_list['可卖数量'].loc[0]) num = min(sell_num.get() * self.base_pramid_ratio, num) num = ac.ShouShu(num) if num > 0: account.Order(1, code, price, num) #更新卖出均价 new_sell_avg_price = (sell_avg_price.get() * sell_num.get()+price*num)/(sell_num.get()+num) sell_avg_price.set(new_sell_avg_price) sell_num.set(sell_num.get()+num)