Пример #1
0
 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
Пример #2
0
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'净利润万元']]
Пример #3
0
    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)
Пример #4
0
    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
Пример #5
0
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()
Пример #6
0
    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)
Пример #7
0
    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()
Пример #8
0
    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)