Ejemplo n.º 1
0
 def test_value_at_risk(self, test_cutoff):
     # empyrical can't tolerate NaNs here
     res_a = empyrical.value_at_risk(ret['a'].iloc[1:], cutoff=test_cutoff)
     res_b = empyrical.value_at_risk(ret['b'].iloc[1:], cutoff=test_cutoff)
     res_c = empyrical.value_at_risk(ret['c'].iloc[1:], cutoff=test_cutoff)
     assert isclose(ret['a'].vbt.returns.value_at_risk(cutoff=test_cutoff),
                    res_a)
     pd.testing.assert_series_equal(
         ret.vbt.returns.value_at_risk(cutoff=test_cutoff),
         pd.Series([res_a, res_b, res_c], index=ret.columns))
Ejemplo n.º 2
0
 def test_value_at_risk(self, test_cutoff):
     # empyrical can't tolerate NaN here
     res_a = empyrical.value_at_risk(ret['a'].iloc[1:], cutoff=test_cutoff)
     res_b = empyrical.value_at_risk(ret['b'].iloc[1:], cutoff=test_cutoff)
     res_c = empyrical.value_at_risk(ret['c'].iloc[1:], cutoff=test_cutoff)
     assert isclose(ret['a'].vbt.returns.value_at_risk(cutoff=test_cutoff),
                    res_a)
     pd.testing.assert_series_equal(
         ret.vbt.returns.value_at_risk(cutoff=test_cutoff),
         pd.Series([res_a, res_b, res_c],
                   index=ret.columns).rename('value_at_risk'))
     pd.testing.assert_series_equal(
         ret.vbt.returns.rolling_value_at_risk(ret.shape[0],
                                               minp=1,
                                               cutoff=test_cutoff).iloc[-1],
         pd.Series([res_a, res_b, res_c],
                   index=ret.columns).rename(ret.index[-1]))
Ejemplo n.º 3
0
        def _func(_p):
            _p._set_kwargs(**self._kwargs)
            _ret = self._returns[_p._id]

            var = ep.value_at_risk(_ret)

            _p.__log__('VaR: %s' % var)
            self._vars[_p._id] = var

            v = var * self._weights[_p._id]

            return v
Ejemplo n.º 4
0
def _get_backtest_performance_metrics(ret, benchmark_ret):
    metrics = {
        'alpha': empyrical.alpha(ret, benchmark_ret),
        'beta': empyrical.beta(ret, benchmark_ret),
        'return': empyrical.cum_returns_final(ret),
        'cagr': empyrical.cagr(ret),
        'sharpe': empyrical.sharpe_ratio(ret),
        'max_drawdown': empyrical.max_drawdown(ret),
        'var': empyrical.value_at_risk(ret),
        'volatility': empyrical.annual_volatility(ret),
    }

    return metrics
Ejemplo n.º 5
0
def plot_function(epoch_weights):
    ew = np.concatenate(epoch_weights).reshape(-1, No_Channels)
    comm = np.sum(np.abs(ew[1:] - ew[:-1]), axis=1)
    ret = np.sum(np.multiply(ew, y_test.numpy()), axis=1)[1:]
    ind = pd.date_range("20180101", periods=len(ret), freq='H')
    ret = pd.DataFrame(ret - comm * cost, index = ind)
    exp = np.exp(ret.resample('1D').sum()) - 1.0
    ggg = 'Drawdown:', emp.max_drawdown(exp).values[0], 'Sharpe:', emp.sharpe_ratio(exp)[0], \
    'Sortino:', emp.sortino_ratio(exp).values[0], 'Stability:', emp.stability_of_timeseries(exp), \
    'Tail:', emp.tail_ratio(exp), 'ValAtRisk:', emp.value_at_risk(exp)
    ttt = ' '.join(str(x) for x in ggg)
    print(ttt)
    plt.figure()
    np.exp(ret).cumprod().plot(figsize=(48, 12), title=ttt)
    plt.savefig('cumulative_return')
    plt.close()
    ret = ret.resample('1W').sum()
    plt.figure(figsize=(48, 12))
    pal = sns.color_palette("Greens_d", len(ret))
    rank = ret.iloc[:,0].argsort()
    ax = sns.barplot(x=ret.index.strftime('%d-%m'), y=ret.values.reshape(-1), palette=np.array(pal[::-1])[rank])
    ax.text(0.5, 1.0, ttt, horizontalalignment='center', verticalalignment='top', transform=ax.transAxes)
    plt.savefig('weekly_returns')
    plt.close()
    ew_df = pd.DataFrame(ew)
    plt.figure(figsize=(48, 12))
    ax = sns.heatmap(ew_df.T, cmap=cmap, center=0, xticklabels=False, robust=True)
    ax.text(0.5, 1.0, ttt, horizontalalignment='center', verticalalignment='top', transform=ax.transAxes)
    plt.savefig('portfolio_weights')
    plt.close()
    tr = np.diff(ew.T, axis=1)
    plt.figure(figsize=(96, 12))
    ax = sns.heatmap(tr, cmap=cmap, center=0, robust=True, yticklabels=False, xticklabels=False)
    ax.text(0.5, 1.0, ttt, horizontalalignment='center', verticalalignment='top', transform=ax.transAxes)
    plt.savefig('transactions')
    plt.close()
Ejemplo n.º 6
0
    def calculate_statistics(self, df: DataFrame = None, output=True):
        """"""
        self.output("开始计算策略统计指标")

        # Check DataFrame input exterior
        if df is None:
            df = self.daily_df

        # Check for init DataFrame
        if df is None:
            # Set all statistics to 0 if no trade.
            start_date = ""
            end_date = ""
            total_days = 0
            profit_days = 0
            loss_days = 0
            end_balance = 0
            max_drawdown = 0
            max_ddpercent = 0
            max_drawdown_duration = 0
            max_drawdown_end = 0
            total_net_pnl = 0
            daily_net_pnl = 0
            total_commission = 0
            daily_commission = 0
            total_slippage = 0
            daily_slippage = 0
            total_turnover = 0
            daily_turnover = 0
            total_trade_count = 0
            daily_trade_count = 0
            total_return = 0
            annual_return = 0
            daily_return = 0
            return_std = 0
            sharpe_ratio = 0
            sortino_info = 0
            win_ratio = 0
            return_drawdown_ratio = 0
            tail_ratio_info = 0
            stability_return = 0
            win_loss_pnl_ratio = 0
            pnl_medio = 0
            duration_medio = 0
            calmar_ratio = 0
        else:
            # Calculate balance related time series data
            df["balance"] = df["net_pnl"].cumsum() + self.capital
            df["return"] = np.log(df["balance"] /
                                  df["balance"].shift(1)).fillna(0)
            df["highlevel"] = (df["balance"].rolling(min_periods=1,
                                                     window=len(df),
                                                     center=False).max())
            df["drawdown"] = df["balance"] - df["highlevel"]
            df["ddpercent"] = df["drawdown"] / df["highlevel"] * 100

            # Calculate statistics value
            start_date = df.index[0]
            end_date = df.index[-1]

            total_days = len(df)
            profit_days = len(df[df["net_pnl"] > 0])
            loss_days = len(df[df["net_pnl"] < 0])

            end_balance = df["balance"].iloc[-1]
            max_drawdown = df["drawdown"].min()
            max_ddpercent = df["ddpercent"].min()
            max_drawdown_end = df["drawdown"].idxmin()

            if isinstance(max_drawdown_end, date):
                max_drawdown_start = df["balance"][:max_drawdown_end].idxmax()
                max_drawdown_duration = (max_drawdown_end -
                                         max_drawdown_start).days
            else:
                max_drawdown_duration = 0

            total_net_pnl = df["net_pnl"].sum()
            daily_net_pnl = total_net_pnl / total_days

            win = df[df["net_pnl"] > 0]
            win_amount = win["net_pnl"].sum()
            win_pnl_medio = win["net_pnl"].mean()
            # win_duration_medio = win["duration"].mean().total_seconds()/3600
            win_count = win["trade_count"].sum()
            pnl_medio = df["net_pnl"].mean()
            # duration_medio = df["duration"].mean().total_seconds()/3600

            loss = df[df["net_pnl"] < 0]
            loss_amount = loss["net_pnl"].sum()
            loss_pnl_medio = loss["net_pnl"].mean()
            # loss_duration_medio = loss["duration"].mean().total_seconds()/3600

            total_commission = df["commission"].sum()
            daily_commission = total_commission / total_days

            total_slippage = df["slippage"].sum()
            daily_slippage = total_slippage / total_days

            total_turnover = df["turnover"].sum()
            daily_turnover = total_turnover / total_days

            total_trade_count = df["trade_count"].sum()
            win_ratio = (win_count / total_trade_count) * 100
            win_loss_pnl_ratio = -win_pnl_medio / loss_pnl_medio
            daily_trade_count = total_trade_count / total_days

            total_return = (end_balance / self.capital - 1) * 100
            annual_return = total_return / total_days * 240
            daily_return = df["return"].mean() * 100
            return_std = df["return"].std() * 100

            if return_std:
                sharpe_ratio = daily_return / return_std * np.sqrt(240)
            else:
                sharpe_ratio = 0

            return_drawdown_ratio = -total_return / max_ddpercent

            #calmar_ratio:年化收益率与历史最大回撤率之间的比率
            calmar_ratio = annual_return / abs(max_ddpercent)

            #sortino_info
            sortino_info = sortino_ratio(df['return'])
            omega_info = omega_ratio(df['return'])
            #年化波动率
            annual_volatility_info = annual_volatility(df['return'])
            #年化复合增长率
            cagr_info = cagr(df['return'])
            #年化下行风险率
            annual_downside_risk = downside_risk(df['return'])
            """CVaR即条件风险价值,其含义为在投资组合的损失超过某个给定VaR值的条件下,该投资组合的平均损失值。"""
            c_var = conditional_value_at_risk(df['return'])
            """风险价值(VaR)是对投资损失风险的一种度量。它估计在正常的市场条件下,在设定的时间段(例如一天)中,
            一组投资可能(以给定的概率)损失多少。金融业中的公司和监管机构通常使用VaR来衡量弥补可能损失所需的资产数量"""
            var_info = value_at_risk(df['return'])

            #收益稳定率
            stability_return = stability_of_timeseries(df['return'])
            #尾部比率0.25 == 1/4,收益1,风险4
            tail_ratio_info = tail_ratio(df['return'])

        # Output
        if output:
            self.output("-" * 30)
            self.output(f"首个交易日:\t{start_date}")
            self.output(f"最后交易日:\t{end_date}")

            self.output(f"总交易日:\t{total_days}")
            self.output(f"盈利交易日:\t{profit_days}")
            self.output(f"亏损交易日:\t{loss_days}")

            self.output(f"起始资金:\t{self.capital:,.2f}")
            self.output(f"结束资金:\t{end_balance:,.2f}")

            self.output(f"总收益率:\t{total_return:,.2f}%")
            self.output(f"年化收益:\t{annual_return:,.2f}%")
            self.output(f"最大回撤: \t{max_drawdown:,.2f}")
            self.output(f"百分比最大回撤: {max_ddpercent:,.2f}%")
            self.output(f"最长回撤天数: \t{max_drawdown_duration}")

            self.output(f"总盈亏:\t{total_net_pnl:,.2f}")
            self.output(f"总手续费:\t{total_commission:,.2f}")
            self.output(f"总滑点:\t{total_slippage:,.2f}")
            self.output(f"总成交金额:\t{total_turnover:,.2f}")
            self.output(f"总成交笔数:\t{total_trade_count}")

            self.output(f"日均盈亏:\t{daily_net_pnl:,.2f}")
            self.output(f"日均手续费:\t{daily_commission:,.2f}")
            self.output(f"日均滑点:\t{daily_slippage:,.2f}")
            self.output(f"日均成交金额:\t{daily_turnover:,.2f}")
            self.output(f"日均成交笔数:\t{daily_trade_count}")

            self.output(f"日均收益率:\t{daily_return:,.2f}%")
            self.output(f"收益标准差:\t{return_std:,.2f}%")
            self.output(f"胜率:\t{win_ratio:,.2f}")
            self.output(f"盈亏比:\t\t{win_loss_pnl_ratio:,.2f}")

            self.output(f"平均每笔盈亏:\t{pnl_medio:,.2f}")
            self.output(f"calmar_ratio:\t{calmar_ratio:,.3f}")
            # self.output(f"平均持仓小时:\t{duration_medio:,.2f}")
            self.output(f"Sharpe Ratio:\t{sharpe_ratio:,.2f}")
            self.output(f"sortino Ratio:\t{sortino_info:,.3f}")
            self.output(f"收益回撤比:\t{return_drawdown_ratio:,.2f}")

        statistics = {
            "start_date": start_date,
            "end_date": end_date,
            "total_days": total_days,
            "profit_days": profit_days,
            "loss_days": loss_days,
            "capital": self.capital,
            "end_balance": end_balance,
            "max_drawdown": max_drawdown,
            "max_ddpercent": max_ddpercent,
            "max_drawdown_end": max_drawdown_end,
            "max_drawdown_duration": max_drawdown_duration,
            "total_net_pnl": total_net_pnl,
            "daily_net_pnl": daily_net_pnl,
            "total_commission": total_commission,
            "daily_commission": daily_commission,
            "total_slippage": total_slippage,
            "daily_slippage": daily_slippage,
            "total_turnover": total_turnover,
            "daily_turnover": daily_turnover,
            "total_trade_count": total_trade_count,
            "daily_trade_count": daily_trade_count,
            "total_return": total_return,
            "annual_return": annual_return,
            "daily_return": daily_return,
            "return_std": return_std,
            "sharpe_ratio": sharpe_ratio,
            'sortino_info': sortino_info,
            "win_ratio": win_ratio,
            "return_drawdown_ratio": return_drawdown_ratio,
            "tail_ratio_info": tail_ratio_info,
            "stability_return": stability_return,
            "win_loss_pnl_ratio": win_loss_pnl_ratio,
            "pnl_medio": pnl_medio,
            "calmar_ratio": calmar_ratio
        }

        # Filter potential error infinite value
        for key, value in statistics.items():
            if value in (np.inf, -np.inf):
                value = 0
            statistics[key] = np.nan_to_num(value)

        self.output("策略统计指标计算完成")
        return statistics
Ejemplo n.º 7
0
def runstrategy(ticker_list,bench_ticker):
    args = parse_args()
    print(args)

    # Create a cerebro
    cerebro = bt.Cerebro()

    # Get the dates from the args
    fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d')
    todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d')

    # bench = bt.feeds.YahooFinanceData(
    #     dataname=bench_ticker,
    #     fromdate=fromdate,
    #     todate=todate,
    #     buffered=True,plot = False
    # )

    bench = bt.feeds.GenericCSVData(
        dataname='/Users/joan/PycharmProjects/CSV_DB/IB/' + bench_ticker + '.csv',
        fromdate=fromdate,
        todate=todate,
        nullvalue=0.0,
        dtformat=('%Y%m%d'),
        datetime=1,
        open=2,
        high=3,
        low=4,
        close=5,
        volume=6,
        reverse=False,
        plot=False)

    cerebro.adddata(bench, name=bench_ticker)

    for i in ticker_list:
        print('Loading data: '+ i)
        # data = bt.feeds.YahooFinanceData(
        #     dataname=i,
        #     fromdate=fromdate,
        #     todate=todate,
        #     adjclose=True,
        #     buffered=True, plot = False
        #     )

        data = bt.feeds.GenericCSVData(
            dataname='/Users/joan/PycharmProjects/CSV_DB/IB/'+i+'.csv',
            fromdate=fromdate,
            todate=todate,
            nullvalue=0.0,
            dtformat=('%Y%m%d'),
            datetime=1,
            open=2,
            high=3,
            low=4,
            close=5,
            volume=6,
            reverse=False,
            plot= False)


        cerebro.adddata(data,name = i)




    # Add the strategy
    cerebro.addstrategy(PairTradingStrategy,
                        period=args.period,
                        stake=args.stake)

    # Add the commission - only stocks like a for each operation
    cerebro.broker.setcash(args.cash)

    # Add the commission - only stocks like a for each operation
    # cerebro.broker.setcommission(commission=args.commperc)

    comminfo = FixedCommisionScheme()
    cerebro.broker.addcommissioninfo(comminfo)

    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe_ratio')

    cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta")
    cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
    cerebro.addanalyzer(bt.analyzers.SharpeRatio_A, _name='myysharpe', riskfreerate=args.rf_rate)
    cerebro.addanalyzer(bt.analyzers.PyFolio, _name='mypyf')
    cerebro.addanalyzer(bt.analyzers.TimeReturn, timeframe=bt.TimeFrame.Days,
                        data=bench, _name='benchreturns')

    cerebro.addobserver(bt.observers.Value)
    cerebro.addobserver(bt.observers.Benchmark,plot = False)
    cerebro.addobserver(bt.observers.DrawDown)

    # And run it
    strat = cerebro.run(runonce=not args.runnext,
                preload=not args.nopreload,
                oldsync=args.oldsync
                )

    # Plot if requested
    if args.plot:
        cerebro.plot(style='candlestick', barup='green', bardown='red',figsize=(100,100))





    bench_returns = strat[0].analyzers.benchreturns.get_analysis()
    bench_df = pd.DataFrame.from_dict(bench_returns, orient='index', columns=['return'])
    return_df = pd.DataFrame.from_dict(strat[0].analyzers.mypyf.get_analysis()['returns'], orient='index',
                                       columns=['return'])

    # print('Sharpe Ratio(bt):', firstStrat.analyzers.myysharpe.get_analysis()['sharperatio'])
    # print('Sharpe Ratio:', empyrical.sharpe_ratio(return_df, risk_free=args.rf_rate / 252, period='daily')[0])
    # print('Sharpe Ratio Benchmark:', empyrical.sharpe_ratio(bench_df, risk_free=args.rf_rate / 252, period='daily')[0])
    # print('')
    #
    # print('Sortino Ratio:', empyrical.sortino_ratio(return_df, period='daily')[0])
    # print('Sortino Ratio Benchmark:', empyrical.sortino_ratio(bench_df, period='daily')[0])
    # print('')
    # print('VaR:', empyrical.value_at_risk(return_df) * 100, '%')
    # print('VaR Benchmark:', empyrical.value_at_risk(bench_df) * 100, '%')
    #
    # print('')
    #
    # print('Capture:', round(empyrical.capture(return_df, bench_df, period='daily')[0] * 100), '%')
    # print('')
    #
    # print('Max drawdown: ', round(empyrical.max_drawdown(return_df)[0] * 100), '%')
    # print('Max drawdown Benchmark: ', round(empyrical.max_drawdown(bench_df)[0] * 100), '%')
    #
    # print('')
    alpha, beta = empyrical.alpha_beta(return_df, bench_df, risk_free=args.rf_rate)
    # print('Beta: ', beta)
    # print('')
    # print('Annual return:', round(empyrical.annual_return(return_df)[0] * 100), '%')
    # print('Annual Vol:', round(empyrical.annual_volatility(return_df)[0] * 100), '%')
    # print('')
    # print('Annual return Benchmark:', round(empyrical.annual_return(bench_df)[0] * 100), '%')
    # print('Annual Vol Benchmark:', round(empyrical.annual_volatility(bench_df)[0] * 100), '%')
    # print('')

    dic = {'SQN': printSQN(strat[0].analyzers.sqn.get_analysis()),
            'sharpe': empyrical.sharpe_ratio(return_df, risk_free=args.rf_rate / 252, period='daily')[0],
           'sharpe_bm': empyrical.sharpe_ratio(bench_df, risk_free=args.rf_rate / 252, period='daily')[0],
           'sortino': empyrical.sortino_ratio(bench_df, period='daily')[0],
           'sortino_bm': empyrical.sortino_ratio(bench_df, period='daily')[0],
           'VaR': empyrical.value_at_risk(return_df) * 100,
           'VaR_bm': empyrical.value_at_risk(bench_df) * 100,
           'capture': round(empyrical.capture(return_df, bench_df, period='daily')[0] * 100),
           'max_dd': round(empyrical.max_drawdown(return_df)[0] * 100),
           'max_dd_bm':round(empyrical.max_drawdown(bench_df)[0] * 100),
           'beta': beta,
           'return_annual':round(empyrical.annual_return(return_df)[0] * 100,2),
           'return_annual_bm':round(empyrical.annual_volatility(return_df)[0] * 100,2),
           'vol_annual':round(empyrical.annual_return(bench_df)[0] * 100,2),
           'vol_annual_bm':round(empyrical.annual_volatility(bench_df)[0] * 100,2)}

    df = pd.DataFrame(dic,index = [0])
    print(df)

    def calc_stats(df):
        df['perc_ret'] = (1 + df['return']).cumprod() - 1
        # print(df.tail())
        return df

    s = return_df.rolling(30).std()
    b = bench_df.rolling(30).std()

    # Get final portfolio Value
    portvalue = cerebro.broker.getvalue()

    # Print out the final result
    print('Final Portfolio Value: ${}'.format(round(portvalue)), 'PnL: ${}'.format(round(portvalue - args.cash)),
          'PnL: {}%'.format(((portvalue / args.cash) - 1) * 100))

    # Finally plot the end results

    if args.plot:


        fig, axs = plt.subplots(2, sharex=True)
        fig.autofmt_xdate()

        axs[1].plot(s)
        axs[1].plot(b)

        axs[1].set_title('Drawdown')
        axs[1].legend(['Fund', 'Benchmark'])

        axs[0].set_title('Returns')
        axs[0].plot(calc_stats(return_df)['perc_ret'])
        axs[0].plot(calc_stats(bench_df)['perc_ret'])
        axs[0].legend(['Fund', 'Benchmark'])
        plt.show()
Ejemplo n.º 8
0
def rovar(excess_returns_series):
    return excess_returns_series.mean() / np.abs(ep.value_at_risk(excess_returns_series))
Ejemplo n.º 9
0
def value_at_risk(portfolio_daily_returns, probability=0.05):
    return ep.value_at_risk(portfolio_daily_returns, probability)
Ejemplo n.º 10
0
    firstStrat.analyzers.mypyf.get_analysis()['returns'],
    orient='index',
    columns=['return'])

# print('Sharpe Ratio(bt):', firstStrat.analyzers.myysharpe.get_analysis()['sharperatio'])
print('Sharpe Ratio:',
      empyrical.sharpe_ratio(return_df, risk_free=rf / 252, period='daily')[0])
print('Sharpe Ratio Benchmark:',
      empyrical.sharpe_ratio(bench_df, risk_free=rf / 252, period='daily')[0])
print('')

print('Sortino Ratio:', empyrical.sortino_ratio(return_df, period='daily')[0])
print('Sortino Ratio Benchmark:',
      empyrical.sortino_ratio(bench_df, period='daily')[0])
print('')
print('VaR:', empyrical.value_at_risk(return_df) * 100, '%')
print('VaR Benchmark:', empyrical.value_at_risk(bench_df) * 100, '%')

print('')

print('Capture:',
      round(empyrical.capture(return_df, bench_df, period='daily')[0] * 100),
      '%')
print('')

print('Max drawdown: ', round(empyrical.max_drawdown(return_df)[0] * 100), '%')
print('Max drawdown Benchmark: ',
      round(empyrical.max_drawdown(bench_df)[0] * 100), '%')

print('')
alpha, beta = empyrical.alpha_beta(return_df, bench_df, risk_free=rf)