示例#1
0
 def test_calmar_ratio(self):
     res_a = empyrical.calmar_ratio(ret['a'])
     res_b = empyrical.calmar_ratio(ret['b'])
     res_c = empyrical.calmar_ratio(ret['c'])
     assert isclose(ret['a'].vbt.returns.calmar_ratio(), res_a)
     pd.testing.assert_series_equal(
         ret.vbt.returns.calmar_ratio(),
         pd.Series([res_a, res_b, res_c], index=ret.columns))
示例#2
0
 def test_calmar_ratio(self):
     res_a = empyrical.calmar_ratio(ret['a'])
     res_b = empyrical.calmar_ratio(ret['b'])
     res_c = empyrical.calmar_ratio(ret['c'])
     assert isclose(ret['a'].vbt.returns.calmar_ratio(), res_a)
     pd.testing.assert_series_equal(
         ret.vbt.returns.calmar_ratio(),
         pd.Series([res_a, res_b, res_c],
                   index=ret.columns).rename('calmar_ratio'))
     pd.testing.assert_series_equal(
         ret.vbt.returns.rolling_calmar_ratio(ret.shape[0],
                                              minp=1).iloc[-1],
         pd.Series([res_a, res_b, res_c],
                   index=ret.columns).rename(ret.index[-1]))
示例#3
0
    def _get_reward(self) -> float:
        """
        This method computes the reward from each action, by looking at the annualized
        ratio, provided in the reward_function
        :return: annualized value of the selected reward ratio
        """
        lookback = min(self.current_step, self._returns_lookback)
        returns = np.diff(self.portfolio[-lookback:])

        if np.count_nonzero(returns) < 1:
            return 0

        if np.count_nonzero(returns) < 1:
            return 0

        if self._reward_function == 'sortino':
            reward = sortino_ratio(returns, annualization=365 * 24)
        elif self._reward_function == 'calmar':
            reward = calmar_ratio(returns, annualization=365 * 24)
        elif self._reward_function == 'omega':
            reward = omega_ratio(returns, annualization=365 * 24)
        else:
            reward = returns[-1]

        return reward if np.isfinite(reward) else 0
示例#4
0
文件: tsmom.py 项目: bigdig/TSMOM
def get_perf_att(series, bnchmark, rf=0.03 / 12, freq='monthly'):
    """F: that provides performance statistic of the returns
    params
    -------

        series: daily or monthly returns

    returns:
        dataframe of Strategy name and statistics"""
    port_mean, port_std, port_sr = (get_stats(series, dtime=freq))
    perf = pd.Series(
        {
            'Annualized_Mean':
            '{:,.2f}'.format(round(port_mean, 3)),
            'Annualized_Volatility':
            round(port_std, 3),
            'Sharpe Ratio':
            round(port_sr, 3),
            'Calmar Ratio':
            round(empyrical.calmar_ratio(series, period=freq), 3),
            'Alpha':
            round(empyrical.alpha(series, bnchmark, risk_free=rf, period=freq),
                  3),
            'Beta':
            round(empyrical.beta(series, bnchmark), 3),
            'Max Drawdown':
            '{:,.2%}'.format(drawdown(series, ret_='nottext')),
            'Sortino Ratio':
            round(
                empyrical.sortino_ratio(
                    series, required_return=rf, period=freq), 3),
        }, )
    perf.name = series.name
    return perf.to_frame()
    def evaluation(self):
        ap.sound(f'entry: create_df')

        mdd = empyrical.max_drawdown(self.df.eac_stgy_rt)
        stgy_ret_an = empyrical.annual_return(self.df.eac_stgy_rt, annualization=self.cls.annualization)
        bcmk_ret_an = empyrical.annual_return(self.df.eac_bcmk_rt, annualization=self.cls.annualization)
        stgy_vlt_an = empyrical.annual_volatility(self.df.eac_stgy_rt, annualization=self.cls.annualization)
        bcmk_vlt_an = empyrical.annual_volatility(self.df.eac_bcmk_rt, annualization=self.cls.annualization)
        calmar = empyrical.calmar_ratio(self.df.eac_stgy_rt, annualization=self.cls.annualization)
        omega = empyrical.omega_ratio(self.df.eac_stgy_rt, risk_free=self.cls.rf, annualization=self.cls.annualization)
        sharpe = qp.sharpe_ratio(stgy_ret_an, self.df.cum_stgy_rt, self.cls.rf)
        sortino = empyrical.sortino_ratio(self.df.eac_stgy_rt, annualization=self.cls.annualization)
        dsrk = empyrical.downside_risk(self.df.eac_stgy_rt, annualization=self.cls.annualization)
        information = empyrical.information_ratio(self.df.eac_stgy_rt, factor_returns=self.df.eac_bcmk_rt)
        beta = empyrical.beta(self.df.eac_stgy_rt, factor_returns=self.df.eac_bcmk_rt, risk_free=self.cls.rf)
        tail_rt = empyrical.tail_ratio(self.df.eac_stgy_rt)
        alpha = qp.alpha_ratio(stgy_ret_an, bcmk_ret_an, self.cls.rf, beta)

        stgy_ttrt_rt = (self.cls.yd.ttas[-1] - self.cls.yd.ttas[0]) / self.cls.yd.ttas[0]
        bcmk_ttrt_rt = (self.cls.pc.close[-1] - self.cls.pc.close[0]) / self.cls.pc.close[0]
        car_rt = stgy_ttrt_rt - bcmk_ttrt_rt
        car_rt_an = stgy_ret_an - bcmk_ret_an

        self.cls.df_output = pd.DataFrame(
            {'sgty_ttrt_rt': [stgy_ttrt_rt], 'bcmk_ttrt_rt': [bcmk_ttrt_rt], 'car_rt': [car_rt],
             'stgy_ret_an': [stgy_ret_an], 'bcmk_ret_an': [bcmk_ret_an], 'car_rt_an': [car_rt_an],
             'stgy_vlt_an': [stgy_vlt_an], 'bcmk_vlt_an': [bcmk_vlt_an], 'mdd': [mdd],
             'sharpe': [sharpe], 'alpha': [alpha], 'beta': [beta], 'information': [information],
             'tail_rt': [tail_rt], 'calmar': [calmar], 'omega': [omega], 'sortino': [sortino], 'dsrk': [dsrk]})
        print(f'feedback: \n{self.cls.df_output.T}')
示例#6
0
def calmar_ratio(returns, period=DAILY):
    """
    Determines the Calmar ratio, or drawdown ratio, of a strategy.

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
        - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
    period : str, optional
        Defines the periodicity of the 'returns' data for purposes of
        annualizing. Can be 'monthly', 'weekly', or 'daily'.
        - Defaults to 'daily'.

    Returns
    -------
    float
        Calmar ratio (drawdown ratio) as float. Returns np.nan if there is no
        calmar ratio.

    Note
    -----
    See https://en.wikipedia.org/wiki/Calmar_ratio for more details.
    """

    return empyrical.calmar_ratio(returns, period=period)
示例#7
0
def calmar_ratio(returns, period=DAILY):
    """
    Determines the Calmar ratio, or drawdown ratio, of a strategy.

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
        - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
    period : str, optional
        Defines the periodicity of the 'returns' data for purposes of
        annualizing. Can be 'monthly', 'weekly', or 'daily'.
        - Defaults to 'daily'.

    Returns
    -------
    float
        Calmar ratio (drawdown ratio) as float. Returns np.nan if there is no
        calmar ratio.

    Note
    -----
    See https://en.wikipedia.org/wiki/Calmar_ratio for more details.
    """

    return ep.calmar_ratio(returns, period=period)
示例#8
0
 def test_calmar(self, returns, period, expected):
     assert_almost_equal(
         empyrical.calmar_ratio(
             returns,
             period=period
         ),
         expected,
         DECIMAL_PLACES)
示例#9
0
def calmar_ratio(daily_returns, period="daily"):
    """Calmar Ratio"""
    try:
        logger.info('Calculating Calmar Ratio...')
        calmar = empyrical.calmar_ratio(daily_returns, period=period)
        return calmar
    except Exception as exception:
        logger.error('Oops! An Error Occurred ⚠️')
        raise exception
示例#10
0
    def plot(self):
        # show a plot of portfolio vs mean market performance
        df_info = pd.DataFrame(self.infos)
        df_info.set_index('current step', inplace=True)
        #   df_info.set_index('date', inplace=True)
        rn = np.asarray(df_info['portfolio return'])

        try:
            spf = df_info['portfolio value'].iloc[1]  #   Start portfolio value
            epf = df_info['portfolio value'].iloc[-1]  #   End portfolio value
            pr = (epf - spf) / spf
        except:
            pr = 0

        try:
            sr = sharpe_ratio(rn)
        except:
            sr = 0

        try:
            sor = sortino_ratio(rn)
        except:
            sor = 0

        try:
            mdd = max_drawdown(rn)
        except:
            mdd = 0

        try:
            cr = calmar_ratio(rn)
        except:
            cr = 0

        try:
            om = omega_ratio(rn)
        except:
            om = 0

        try:
            dr = downside_risk(rn)
        except:
            dr = 0

        print("First portfolio value: ",
              np.round(df_info['portfolio value'].iloc[1]))
        print("Last portfolio value: ",
              np.round(df_info['portfolio value'].iloc[-1]))

        title = self.strategy_name + ': ' + 'profit={: 2.2%} sharpe={: 2.2f} sortino={: 2.2f} max drawdown={: 2.2%} calmar={: 2.2f} omega={: 2.2f} downside risk={: 2.2f}'.format(
            pr, sr, sor, mdd, cr, om, dr)
        #   df_info[['market value', 'portfolio value']].plot(title=title, fig=plt.gcf(), figsize=(15,10), rot=30)
        df_info[['portfolio value']].plot(title=title,
                                          fig=plt.gcf(),
                                          figsize=(15, 10),
                                          rot=30)
示例#11
0
    def _get_reward(self, current_prices, next_prices):
        if self.compute_reward == compute_reward.profit:
            returns_rate = next_prices / current_prices
            #   pip_value = self._calculate_pip_value_in_account_currency(account_currency.USD, next_prices)
            #   returns_rate = np.multiply(returns_rate, pip_value)
            log_returns = np.log(returns_rate)
            last_weight = self.current_weights
            securities_value = self.current_portfolio_values[:-1] * returns_rate
            self.current_portfolio_values[:-1] = securities_value
            self.current_weights = self.current_portfolio_values / np.sum(
                self.current_portfolio_values)
            reward = last_weight[:-1] * log_returns
        elif self.compute_reward == compute_reward.sharpe:
            try:
                sr = sharpe_ratio(np.asarray(self.returns))
            except:
                sr = 0
            reward = sr
        elif self.compute_reward == compute_reward.sortino:
            try:
                sr = sortino_ratio(np.asarray(self.returns))
            except:
                sr = 0
            reward = sr
        elif self.compute_reward == compute_reward.max_drawdown:
            try:
                mdd = max_drawdown(np.asarray(self.returns))
            except:
                mdd = 0
            reward = mdd
        elif self.compute_reward == compute_reward.calmar:
            try:
                cr = calmar_ratio(np.asarray(self.returns))
            except:
                cr = 0
            reward = cr
        elif self.compute_reward == compute_reward.omega:
            try:
                om = omega_ratio(np.asarray(self.returns))
            except:
                om = 0
            reward = om
        elif self.compute_reward == compute_reward.downside_risk:
            try:
                dr = downside_risk(np.asarray(self.returns))
            except:
                dr = 0
            reward = dr

        try:
            reward = reward.mean()
        except:
            reward = reward

        return reward
示例#12
0
def _reward(self):
      length = min(self.current_step, self.reward_len)
      returns = np.diff(self.net_worths)[-length:]

      if self.reward_func == 'sortino':
          reward = sortino_ratio(returns)
      elif self.reward_func == 'calmar':
          reward = calmar_ratio(returns)
      elif self.reward_func == 'omega':
          reward = omega_ratio(returns)
      else
          reward = np.mean(returns)

      return reward if abs(reward) != inf and not np.isnan(reward) else 0
示例#13
0
文件: tsmom.py 项目: ssh352/TSMOM
def get_perf_att(series, bnchmark, rf=0.03 / 12, freq='monthly'):
    """F: that provides performance statistic of the returns
    params
    -------

        series: daily or monthly returns

    returns:
        dataframe of Strategy name and statistics"""
    port_mean, port_std, port_sr = (get_stats(series, dtime=freq))

    regs = sm.OLS(series, sm.add_constant(bnchmark)).fit()
    alpha, beta = regs.params
    t_alpha, t_beta = regs.tvalues

    perf = pd.Series(
        {
            'Annualized_Mean':
            '{:,.5f}'.format(round(port_mean, 5)),
            'Annualized_Volatility':
            round(port_std, 5),
            'Sharpe Ratio':
            round(port_sr, 3),
            'Calmar Ratio':
            round(empyrical.calmar_ratio(series, period=freq), 3),
            # 'Alpha' : round(empyrical.alpha(series,
            #                                 bnchmark,
            #                                 risk_free = rf,
            #                                 period = freq),
            'Alpha':
            round(alpha, 3),
            # 'Beta':  round(empyrical.beta(series,
            #                               bnchmark),
            'Beta':
            round(beta, 3),
            'T Value (Alpha)':
            round(t_alpha, 3),
            'T Value (Beta)':
            round(t_beta, 3),
            'Max Drawdown':
            '{:,.2%}'.format(drawdown(series, ret_='nottext')),
            'Sortino Ratio':
            round(
                empyrical.sortino_ratio(
                    series, required_return=rf, period=freq), 3),
        }, )
    perf.name = series.name
    return perf.to_frame()
示例#14
0
    def _reward(self):
        length = min(self.current_step, self.forecast_len)
        returns = np.diff(self.net_worths[-length:])

        if np.count_nonzero(returns) < 1:
            return 0

        if self.reward_func == 'sortino':
            reward = sortino_ratio(returns, annualization=365 * 24)
        elif self.reward_func == 'calmar':
            reward = calmar_ratio(returns, annualization=365 * 24)
        elif self.reward_func == 'omega':
            reward = omega_ratio(returns, annualization=365 * 24)
        else:
            reward = returns[-1]

        return reward if np.isfinite(reward) else 0
    def _reward(self):
        length = min(self.current_step, self.window_size)
        returns = np.diff(self.net_worths[-length:])

        if np.count_nonzero(returns) < 1:
            return 0

        if self.reward_func == 'sortino':
            reward = sortino_ratio(returns, annualization=self.annualization)
        elif self.reward_func == 'calmar':
            reward = calmar_ratio(returns, annualization=self.annualization)
        elif self.reward_func == 'omega':
            reward = omega_ratio(returns, annualization=self.annualization)
        elif self.reward_func == "logret":
            reward = np.log(returns[-1])
        else:
            reward = returns[-1]

        return reward if np.isfinite(reward) else 0
示例#16
0
def get_statistics(ticker, end_date, k):
    """
    得到一只基金在end_date前推k个交易日的
    1. 收益率
    2. 波动率
    3. 最大回撤
    4. Sharpe
    5. Calmar
    """
    fname = '%s/history/%s.xlsx'%(const.DATA_DIR, ticker)
    df = pd.read_excel(fname, index_col=0)
    df = df[df.index <= end_date]
    if k > df.shape[0]:
        return 0, 0, 0, 0, 0

    df = df[df.index >= df.index[-k]]
    df.loc[:, 'return'] = df.loc[:, 'nav_adj'].pct_change()
    returns = (df.ix[-1, 'nav_adj'] - df.ix[0, 'nav_adj']) / df.ix[0, 'nav_adj']
    volatility = empyrical.annual_volatility(df['return'])
    max_drawdown = empyrical.max_drawdown(df['return'])
    sharpe = empyrical.sharpe_ratio(df['return'])
    calmar = empyrical.calmar_ratio(df['return'])
    return returns, volatility, max_drawdown, sharpe, calmar
示例#17
0
 def _calmar(self):
     self.__calmar = ey.calmar_ratio(returns = self.__returns)
示例#18
0
def test():
    # 构造测试数据
    returns = pd.Series(
        index = pd.date_range("2017-03-10", "2017-03-19"),
        data = (-0.012143, 0.045350, 0.030957, 0.004902, 0.002341, -0.02103, 0.00148, 0.004820, -0.00023, 0.01201))
    print(returns)
    benchmark_returns = pd.Series(
        index = pd.date_range("2017-03-10", "2017-03-19"),
        data = ( -0.031940, 0.025350, -0.020957, -0.000902, 0.007341, -0.01103, 0.00248, 0.008820, -0.00123, 0.01091))
    print(benchmark_returns)
    # 计算累积收益率
    creturns = ey.cum_returns(returns)
    print("累积收益率\n", creturns)
    risk = riskAnalyzer(returns, benchmark_returns, riskFreeRate = 0.01)
    results = risk.run()
    print(results)
    # 直接调用empyrical试试
    alpha = ey.alpha(returns = returns, factor_returns = benchmark_returns, risk_free = 0.01)
    calmar = ey.calmar_ratio(returns)
    print(alpha, calmar)
    # 自己计算阿尔法值
    annual_return = ey.annual_return(returns)
    annual_bench = ey.annual_return(benchmark_returns)
    print(annual_return, annual_bench)
    alpha2 = (annual_return - 0.01) - results["贝塔"]*(annual_bench - 0.01)
    print(alpha2)
    # 自己计算阿尔法贝塔
    def get_return(code, startdate, endate):
        df = ts.get_k_data(code, ktype = "D", autype = "qfq", start = startdate, end = endate)
        p1 = np.array(df.close[1:])
        p0 = np.array(df.close[:-1])
        logret = np.log(p1/p0)
        rate = pd.DataFrame()
        rate[code] = logret
        rate.index = df["date"][1:]
        return rate
    def alpha_beta(code, startdate, endate):
        mkt_ret = get_return("sh", startdate, endate)
        stock_ret = get_return(code, startdate, endate)
        df = pd.merge(mkt_ret, stock_ret, left_index = True, right_index = True)
        x = df.iloc[:, 0]
        y = df.iloc[:, 1]
        beta, alpha, r_value, p_value, std_err = stats.linregress(x, y)
        return (alpha, beta)
    def stocks_alpha_beta(stocks, startdate, endate):
        df = pd.DataFrame()
        alpha = []
        beta = []
        for code in stocks.values():
            a, b = alpha_beta(code, startdate, endate)
            alpha.append(float("%.4f"%a))
            beta.append(float("%.4f"%b))
        df["alpha"] = alpha
        df["beta"] = beta
        df.index = stocks.keys()
        return df
        
    startdate = "2017-01-01"
    endate = "2018-11-09"
    stocks={'中国平安':'601318','格力电器':'000651','招商银行':'600036','恒生电子':'600570','中信证券':'600030','贵州茅台':'600519'}
    results = stocks_alpha_beta(stocks, startdate, endate)
    print("自己计算结果")
    print(results)
    
    # 用empyrical计算
    def stocks_alpha_beta2(stocks, startdate, endate):
        df = pd.DataFrame()
        alpha = []
        beta = []
        for code in stocks.values():
            a, b = empyrical_alpha_beta(code, startdate, endate)
            alpha.append(float("%.4f"%a))
            beta.append(float("%.4f"%b))
        df["alpha"] = alpha
        df["beta"] = beta
        df.index = stocks.keys()
        return df
    def empyrical_alpha_beta(code, startdate, endate):
        mkt_ret = get_return("sh", startdate, endate)
        stock_ret = get_return(code, startdate, endate)
        alpha, beta = ey.alpha_beta(returns = stock_ret, factor_returns = mkt_ret,  annualization = 1)
        return (alpha, beta)
        
    results2 = stocks_alpha_beta2(stocks, startdate, endate)
    print("empyrical计算结果")
    print(results2)
    print(results2["alpha"]/results["alpha"])
示例#19
0
    def create_summary_tearsheet(self, performance, agg_performance=None):
        """
        Create a tear sheet of summary performance stats in a table.

        Parameters
        ----------
        performance : DailyPerformance, required
            a DailyPerformance instance

        agg_performance : AggregateDailyPerformance, optional
            an AggregateDailyPerformance instance. Constructed from performance
            if not provided.

        Returns
        -------
        None

        Examples
        --------
        >>> from moonchart import DailyPerformance, Tearsheet
        >>> perf = DailyPerformance.from_moonshot_csv("backtest_results.csv")
        >>> t = Tearsheet()
        >>> t.create_summary_tearsheet(perf)
        """
        if agg_performance is None:
            agg_performance = AggregateDailyPerformance(performance)

        stats = []

        if agg_performance.pnl is not None:
            stats.append(["PNL", round(agg_performance.pnl.sum(), 2)])
        if agg_performance.commission_amounts is not None:
            stats.append([
                "Commissions",
                round(agg_performance.commission_amounts.sum(), 2)
            ])

        stats.append([
            "Start Date",
            agg_performance.returns.index.min().date().isoformat()
        ])
        stats.append([
            "End Date",
            agg_performance.returns.index.max().date().isoformat()
        ])

        stats.append([
            'Total Months',
            round((agg_performance.returns.index.max() -
                   agg_performance.returns.index.min()) / pd.Timedelta(1, 'M'))
        ])

        stats.append(["", " Risk and Returns"])
        stats.append(
            ["CAGR", "{0}%".format(round(agg_performance.cagr * 100, 1))])
        stats.append(["Sharpe Ratio", '%.2f' % agg_performance.sharpe])
        stats.append([
            "Max Drawdown",
            "{0}%".format(round(agg_performance.max_drawdown * 100, 1))
        ])
        stats.append([
            "Cumulative Return", "{0}%".format(
                round(ep.cum_returns_final(agg_performance.returns) * 100, 1))
        ])
        stats.append([
            "Annual Volatility", "{0}%".format(
                round(ep.annual_volatility(agg_performance.returns) * 100, 1))
        ])
        stats.append([
            "Sortino Ratio",
            '%.2f' % ep.sortino_ratio(agg_performance.returns)
        ])
        stats.append([
            "Calmar Ratio",
            '%.2f' % ep.calmar_ratio(agg_performance.returns)
        ])
        stats.append(
            ["Skew",
             '%.2f' % scipy.stats.skew(agg_performance.returns)])
        stats.append([
            "Kurtosis",
            '%.2f' % scipy.stats.kurtosis(agg_performance.returns)
        ])

        if any([
                field is not None for field in (agg_performance.abs_exposures,
                                                agg_performance.net_exposures,
                                                agg_performance.total_holdings,
                                                agg_performance.turnover)
        ]):
            stats.append(["", " Positions and Exposure"])

        if agg_performance.abs_exposures is not None:
            avg_abs_exposures = agg_performance.abs_exposures.mean()
            stats.append([
                "Absolute Exposure (percentage of capital)",
                "{0}%".format(round(avg_abs_exposures * 100, 1))
            ])

        if agg_performance.net_exposures is not None:
            avg_net_exposures = agg_performance.net_exposures.mean()
            stats.append([
                "Net Exposure (percentage of capital)",
                "{0}%".format(round(avg_net_exposures * 100, 1))
            ])

        if agg_performance.total_holdings is not None:
            avg_daily_holdings = agg_performance.total_holdings.mean()
            stats.append(["Average Daily Holdings", round(avg_daily_holdings)])

        if agg_performance.turnover is not None:
            avg_daily_turnover = agg_performance.turnover.mean()
            stats.append([
                "Average Daily Turnover (percentage of capital)",
                "{0}%".format(round(avg_daily_turnover * 100, 1))
            ])

        if agg_performance.abs_exposures is not None:
            norm_cagr = agg_performance.cagr / avg_abs_exposures
            stats.append([
                "Normalized CAGR (CAGR/Absolute Exposure)",
                "{0}%".format(round(norm_cagr * 100, 1))
            ])

        with sns.axes_style("white", {'axes.linewidth': 0}):

            fig = plt.figure("Performance Summary", figsize=(6, 6))

            axis = fig.add_subplot(111)
            axis.get_xaxis().set_visible(False)
            axis.get_yaxis().set_visible(False)

            headings, values = zip(*stats)

            table = axis.table(cellText=[[v] for v in values],
                               rowLabels=headings,
                               colLabels=["Performance Summary"],
                               loc="center")
            for (row, col), cell in table.get_celld().items():
                txt = cell.get_text().get_text()
                if row == 0 or txt.startswith(" "):
                    cell.set_text_props(fontproperties=FontProperties(
                        weight='bold'))

            table.scale(1, 2)
            table.set_fontsize("large")
            fig.tight_layout()
    # convert to daily return for different asset in t
    ind_return = pd.concat([ind_return, df[i + '-ind_return']], axis=1)

#%% Portfolio Average
# Strategy return in daily
ind_return['port_avg'] = ind_return.mean(skipna=1, axis=1)
# convert to monthly basis
strategy_month_rtns = ind_return['port_avg'].resample('BM').last().ffill()

strategy_cumm_rtns['cummulative'] = (1 + ind_return['port_avg']).cumprod()
# convert to monthly cum return
strategy_month = strategy_cumm_rtns['cummulative'].resample('BM').last().ffill()

#%% Print Results
print("Annualized Sharpe Ratio = ", empyrical.sharpe_ratio(ind_return['port_avg'], period='daily'))
print("Annualized Mean Returns = ", empyrical.annual_return(ind_return['port_avg'], period='daily'))
print("Annualized Standard Deviations = ", empyrical.annual_volatility(ind_return['port_avg'], period='daily'))
print("Max Drawdown (MDD) = ", empyrical.max_drawdown(ind_return['port_avg']))
print("Sortino ratio = ", empyrical.sortino_ratio(ind_return['port_avg'], period='daily'))
print("Calmar ratio = ", empyrical.calmar_ratio(ind_return['port_avg'], period='daily'))

#%% Visualization
#print(empyrical.sharpe_ratio(strategy_month_rtns, period='monthly'))
a = empyrical.cum_returns(ind_return['port_avg'])
#b = strategy_month
plt.plot(a, color = 'red', label = 'Raw Portfolio')
plt.title('Cumulative return in daily basis')
plt.xlabel('Time')
plt.ylabel('Cumulative return')
plt.legend()
plt.show()
示例#21
0
def trades(trades_list: list, daily_balance: list):
    starting_balance = 0
    current_balance = 0

    for e in store.exchanges.storage:
        starting_balance += store.exchanges.storage[e].starting_assets[
            jh.app_currency()]
        current_balance += store.exchanges.storage[e].assets[jh.app_currency()]

    starting_balance = round(starting_balance, 2)
    current_balance = round(current_balance, 2)

    if len(trades_list) == 0:
        return None

    df = pd.DataFrame.from_records([t.to_dict() for t in trades_list])

    total_completed = len(df)
    winning_trades = df.loc[df['PNL'] > 0]
    total_winning_trades = len(winning_trades)
    losing_trades = df.loc[df['PNL'] < 0]
    total_losing_trades = len(losing_trades)

    losing_i = df['PNL'] < 0
    losing_streaks = losing_i.ne(losing_i.shift()).cumsum()
    losing_streak = losing_streaks[losing_i].value_counts().max()

    winning_i = df['PNL'] > 0
    winning_streaks = winning_i.ne(winning_i.shift()).cumsum()
    winning_streak = winning_streaks[winning_i].value_counts().max()
    largest_losing_trade = round(df['PNL'].min(), 2)
    largest_winning_trade = round(df['PNL'].max(), 2)

    win_rate = len(winning_trades) / (len(losing_trades) + len(winning_trades))
    max_R = round(df['R'].max(), 2)
    min_R = round(df['R'].min(), 2)
    mean_R = round(df['R'].mean(), 2)
    longs_count = len(df.loc[df['type'] == 'long'])
    shorts_count = len(df.loc[df['type'] == 'short'])
    longs_percentage = longs_count / (longs_count + shorts_count) * 100
    short_percentage = 100 - longs_percentage
    fee = df['fee'].sum()
    net_profit = round(df['PNL'].sum(), 2)
    net_profit_percentage = round((net_profit / starting_balance) * 100, 2)
    average_win = round(winning_trades['PNL'].mean(), 2)
    average_loss = round(abs(losing_trades['PNL'].mean()), 2)
    ratio_avg_win_loss = average_win / average_loss
    expectancy = (0 if np.isnan(average_win) else average_win) * win_rate - (
        0 if np.isnan(average_loss) else average_loss) * (1 - win_rate)
    expectancy = round(expectancy, 2)
    expectancy_percentage = round((expectancy / starting_balance) * 100, 2)
    expected_net_profit_every_100_trades = round(expectancy_percentage * 100,
                                                 2)
    average_holding_period = df['holding_period'].mean()
    average_winning_holding_period = winning_trades['holding_period'].mean()
    average_losing_holding_period = losing_trades['holding_period'].mean()
    gross_profit = round(df.loc[df['PNL'] > 0]['PNL'].sum(), 2)
    gross_loss = round(df.loc[df['PNL'] < 0]['PNL'].sum(), 2)

    daily_returns = pd.Series(daily_balance).pct_change(1).values
    max_drawdown = round(empyrical.max_drawdown(daily_returns) * 100, 2)
    annual_return = round(empyrical.annual_return(daily_returns) * 100, 2)
    sharpe_ratio = round(empyrical.sharpe_ratio(daily_returns), 2)
    calmar_ratio = round(empyrical.calmar_ratio(daily_returns), 2)
    sortino_ratio = round(empyrical.sortino_ratio(daily_returns), 2)
    omega_ratio = round(empyrical.omega_ratio(daily_returns), 2)
    total_open_trades = store.app.total_open_trades
    open_pl = store.app.total_open_pl

    return {
        'total':
        np.nan if np.isnan(total_completed) else total_completed,
        'total_winning_trades':
        np.nan if np.isnan(total_winning_trades) else total_winning_trades,
        'total_losing_trades':
        np.nan if np.isnan(total_losing_trades) else total_losing_trades,
        'starting_balance':
        np.nan if np.isnan(starting_balance) else starting_balance,
        'finishing_balance':
        np.nan if np.isnan(current_balance) else current_balance,
        'win_rate':
        np.nan if np.isnan(win_rate) else win_rate,
        'max_R':
        np.nan if np.isnan(max_R) else max_R,
        'min_R':
        np.nan if np.isnan(min_R) else min_R,
        'mean_R':
        np.nan if np.isnan(mean_R) else mean_R,
        'ratio_avg_win_loss':
        np.nan if np.isnan(ratio_avg_win_loss) else ratio_avg_win_loss,
        'longs_count':
        np.nan if np.isnan(longs_count) else longs_count,
        'longs_percentage':
        np.nan if np.isnan(longs_percentage) else longs_percentage,
        'short_percentage':
        np.nan if np.isnan(short_percentage) else short_percentage,
        'shorts_count':
        np.nan if np.isnan(shorts_count) else shorts_count,
        'fee':
        np.nan if np.isnan(fee) else fee,
        'net_profit':
        np.nan if np.isnan(net_profit) else net_profit,
        'net_profit_percentage':
        np.nan if np.isnan(net_profit_percentage) else net_profit_percentage,
        'average_win':
        np.nan if np.isnan(average_win) else average_win,
        'average_loss':
        np.nan if np.isnan(average_loss) else average_loss,
        'expectancy':
        np.nan if np.isnan(expectancy) else expectancy,
        'expectancy_percentage':
        np.nan if np.isnan(expectancy_percentage) else expectancy_percentage,
        'expected_net_profit_every_100_trades':
        np.nan if np.isnan(expected_net_profit_every_100_trades) else
        expected_net_profit_every_100_trades,
        'average_holding_period':
        average_holding_period,
        'average_winning_holding_period':
        average_winning_holding_period,
        'average_losing_holding_period':
        average_losing_holding_period,
        'gross_profit':
        gross_profit,
        'gross_loss':
        gross_loss,
        'max_drawdown':
        max_drawdown,
        'annual_return':
        annual_return,
        'sharpe_ratio':
        sharpe_ratio,
        'calmar_ratio':
        calmar_ratio,
        'sortino_ratio':
        sortino_ratio,
        'omega_ratio':
        omega_ratio,
        'total_open_trades':
        total_open_trades,
        'open_pl':
        open_pl,
        'winning_streak':
        winning_streak,
        'losing_streak':
        losing_streak,
        'largest_losing_trade':
        largest_losing_trade,
        'largest_winning_trade':
        largest_winning_trade,
    }
示例#22
0
文件: test.py 项目: no7dw/py-practice
    max_drawdown,
    sharpe_ratio,
    sortino_ratio,
    calmar_ratio,
    omega_ratio,
    tail_ratio
)
import pandas as pd
returns = pd.Series(
    index=pd.date_range('2017-03-10', '2017-03-19'),
    data=(-0.012143, 0.045350, 0.030957, 0.004902, 0.002341, -0.02103, 0.00148, 0.004820, -0.00023, 0.01201)
)

benchmark_returns = pd.Series(
    index=pd.date_range('2017-03-10', '2017-03-19'),
    data=(-0.031940, 0.025350, -0.020957, -0.000902, 0.007341, -0.01103, 0.00248, 0.008820, -0.00123, 0.01091)
)
creturns = cum_returns(returns)
max_drawdown(returns)
annual_return(returns)
annual_volatility(returns, period='daily')
calmar_ratio(returns)
omega_ratio(returns=returns, risk_free=0.01)
sharpe_ratio(returns=returns, risk_free=0.01)
sortino_ratio(returns=returns)
downside_risk(returns=returns)
alpha(returns=returns, factor_returns=benchmark_returns, risk_free=0.01)
beta(returns=returns, factor_returns=benchmark_returns, risk_free=0.01)
tail_ratio(returns=returns)

target_vol = 0.15

for i in ast:
    # 进行水平方向的合并
    df = pd.concat([ast[i], predicted_X_t[i + "-X_t"]], axis=1)

    day_vol = df[i].ewm(ignore_na=False, adjust=True, span=60,
                        min_periods=0).std(bias=False)

    # daily return based on equation (1) for individual asset
    df[i + '-ind_return'] = df[i] * df[i + "-X_t"] * target_vol / day_vol

    # convert to daily return for different asset in t
    ind_return = pd.concat([ind_return, df[i + '-ind_return']], axis=1)

# daily return in portfolio
ind_return['port_avg'] = ind_return.mean(skipna=1, axis=1)

#%% Print Results
print("Annualized Sharpe Ratio = ",
      empyrical.sharpe_ratio(ind_return['port_avg'], period='daily'))
print("Annualized Mean Returns = ",
      empyrical.annual_return(ind_return['port_avg'], period='daily'))
print("Annualized Standard Deviations = ",
      empyrical.annual_volatility(ind_return['port_avg'], period='daily'))
print("Max Drawdown (MDD) = ", empyrical.max_drawdown(ind_return['port_avg']))
print("Sortino ratio = ",
      empyrical.sortino_ratio(ind_return['port_avg'], period='daily'))
print("Calmar ratio = ",
      empyrical.calmar_ratio(ind_return['port_avg'], period='daily'))
示例#24
0
 def get_calmar_ratio(self, data):
     data = copy.deepcopy(data)
     calmar_ratio = empyrical.calmar_ratio(data.rets.dropna(),
                                           period='weekly')
     return calmar_ratio
示例#25
0
def run_turtle():
    PROPERTY = START_MONEY
    CASH = START_MONEY

    show_df = None
    show_df = stock_df_dict['NDX'].copy()

    order_df = None
    order_df = pd.DataFrame(columns=[
        'buy_date', 'symbol', 'buy_count', 'buy_price', 'buy_reason',
        'sell_date', 'sell_price', 'sell_reason', 'profit', 'cash', 'property'
    ])
    count_day = 0
    yesterday = None

    for today in pd.period_range(start=start_date, end=end_date, freq='D'):
        count_day += 1

        if yesterday is None:
            yesterday = today
            continue

        if today not in stock_df_dict['NDX'].index:
            continue

        if IS_HAPPY_MONEY:
            if PROPERTY > START_MONEY * 2:
                global HAPPY_MONEY
                HAPPY_MONEY += int(START_MONEY / 2)
                PROPERTY -= int(START_MONEY / 2)
                CASH = PROPERTY

        # 买卖过程
        sell_signal = []
        buy_signal = []

        for symbol in NASDAQ100[:]:
            # for symbol in ['TSLA']:
            if symbol in [
                    'ALGN', 'ROST', 'ORLY', 'ESRX', 'ULTA', 'REGN', 'MNST'
            ]:
                # continue
                pass

            if symbol == 'NDX':
                continue

            if today not in stock_df_dict[
                    symbol].index or yesterday not in stock_df_dict[
                        symbol].index:
                continue

            # 突破下行趋势,清仓退出
            order_arr = order_df.to_records(index=False)
            if len(order_arr[(order_arr.symbol == symbol)
                             & (order_arr.sell_price == 0)]) != 0:
                is_sell = False
                for idx in order_df[(order_df['symbol'] == symbol)
                                    & (order_df['sell_price'] == 0)].index:
                    if order_df.loc[idx, 'buy_reason'] == 'SHORT':
                        is_sell = (
                            stock_df_dict[symbol].loc[today, 'open'] <=
                            stock_df_dict[symbol].loc[today,
                                                      'ROLLING_%d_MIN' %
                                                      TURTLE_SHORT_SELL_N])
                    if order_df.loc[idx, 'buy_reason'] == 'LONG':
                        is_sell = (
                            stock_df_dict[symbol].loc[today, 'open'] <=
                            stock_df_dict[symbol].loc[today,
                                                      'ROLLING_%d_MIN' %
                                                      TURTLE_LONG_SELL_N])
                    if is_sell:
                        CASH += order_df.loc[idx, 'buy_count'] * \
                            stock_df_dict[symbol].loc[today, 'open']
                        order_df.loc[idx, 'sell_date'] = today
                        order_df.loc[idx,
                                     'sell_price'] = stock_df_dict[symbol].loc[
                                         today, 'open']
                        order_df.loc[idx, 'sell_reason'] = 'EXIT'
                        order_df.loc[idx, 'profit'] = \
                            (order_df.loc[idx, 'sell_price'] - order_df.loc[idx, 'buy_price']) * order_df.loc[idx, 'buy_count']
                    # print(today, '退出', stock_df_dict[symbol].loc[today, 'open'], CASH)

            # 突破上行趋势,买入一份
            order_arr = order_df.to_records(index=False)
            if stock_df_dict[symbol].loc[
                    today, 'MA30'] >= stock_df_dict[symbol].loc[today,
                                                                'MA180']:
                is_buy = False
                if stock_df_dict[symbol].loc[today, 'open'] >= stock_df_dict[
                        symbol].loc[today,
                                    'ROLLING_%d_MAX' % TURTLE_LONG_BUY_N]:
                    is_buy = True
                    buy_reason = 'LONG'
                elif stock_df_dict[symbol].loc[today, 'open'] >= stock_df_dict[
                        symbol].loc[today,
                                    'ROLLING_%d_MAX' % TURTLE_SHORT_BUY_N]:
                    is_buy = True
                    buy_reason = 'SHORT'
                if is_buy:
                    buy_count = 0
                    if CASH >= PROPERTY / TURTLE_POS:
                        buy_count = int(
                            (PROPERTY / TURTLE_POS) /
                            stock_df_dict[symbol].loc[today, 'open'])
                    if buy_count > 0:
                        CASH -= buy_count * \
                            stock_df_dict[symbol].loc[today, 'open']
                        # print(today, '买入', buy_count, stock_df_dict[symbol].loc[today, 'open'], CASH)
                        order_df = order_df.append(
                            {
                                'buy_date':
                                today,
                                'symbol':
                                symbol,
                                'buy_count':
                                buy_count,
                                'buy_price':
                                stock_df_dict[symbol].loc[today, 'open'],
                                'buy_reason':
                                buy_reason,
                                'sell_date':
                                pd.np.nan,
                                'sell_price':
                                0,
                                'profit':
                                0,
                                'cash':
                                CASH,
                                'property':
                                PROPERTY,
                            },
                            ignore_index=True)

        # 每天盘点财产
        show_df.loc[today,
                    'CASH_TURTLE_%d_%d_%d' %
                    (TURTLE_POS, TURTLE_LONG_BUY_N, TURTLE_LONG_SELL_N)] = CASH
        PROPERTY = CASH + \
            sum(
                [
                    stock_df_dict[order_df.loc[idx, 'symbol']].loc[today,
                                                                   'open'] * order_df.loc[idx, 'buy_count']
                    for idx in order_df.loc[order_df['sell_price'] == 0].index
                ]
            )
        show_df.loc[today,
                    'PROPERTY_TURTLE_%d_%d_%d' %
                    (TURTLE_POS, TURTLE_LONG_BUY_N,
                     TURTLE_LONG_SELL_N)] = PROPERTY
        yesterday = today

    # 最终结果
    print('CASH', CASH)
    print('HAPPY_MONEY', HAPPY_MONEY)
    print('PROPERTY', PROPERTY)

    benchmark_symbol = 'NDX'
    s_p = stock_df_dict[benchmark_symbol][start_date:].iloc[0].open
    e_p = stock_df_dict[benchmark_symbol].iloc[-1].open
    print(benchmark_symbol, s_p, e_p, e_p / s_p)

    show_df = show_df[start_date:].dropna(how='any', inplace=False)
    show_df['strategy_pct'] = show_df['PROPERTY_TURTLE_%d_%d_%d' %
                                      (TURTLE_POS, TURTLE_LONG_BUY_N,
                                       TURTLE_LONG_SELL_N)].pct_change()
    # show_df['benchmark_pct'] = show_df['open'].pct_change()
    show_df['benchmark_pct'] = stock_df_dict[benchmark_symbol].open.pct_change(
    )
    # print('cum_returns', emp.cum_returns(show_df.strategy_pct))
    print('max_drawdown', emp.max_drawdown(show_df.strategy_pct))
    print(
        'MDD',
        MDD(show_df['PROPERTY_TURTLE_%d_%d_%d' %
                    (TURTLE_POS, TURTLE_LONG_BUY_N, TURTLE_LONG_SELL_N)]))
    print('annual_return', emp.annual_return(show_df.strategy_pct))
    print('annual_volatility',
          emp.annual_volatility(show_df.strategy_pct, period='daily'))
    print('calmar_ratio', emp.calmar_ratio(show_df.strategy_pct))
    print('sharpe_ratio', emp.sharpe_ratio(returns=show_df.strategy_pct))
    print(
        'alpha',
        emp.alpha(returns=show_df.strategy_pct,
                  factor_returns=show_df.benchmark_pct,
                  risk_free=0.00))
    print(
        'beta',
        emp.beta(returns=show_df.strategy_pct,
                 factor_returns=show_df.benchmark_pct,
                 risk_free=0.00))
def Strategy_performance(returns: pd.DataFrame,
                         mark_benchmark: str = 'benchmark',
                         periods: str = 'daily') -> pd.DataFrame:
    '''
    风险指标计算

    returns:index-date col-数据字段
    mark_benchmark:用于指明基准
    periods:频率
    '''

    df: pd.DataFrame = pd.DataFrame()

    df['年化收益率'] = ep.annual_return(returns, period=periods)

    df['累计收益'] = returns.apply(lambda x: ep.cum_returns(x).iloc[-1])

    df['波动率'] = returns.apply(
        lambda x: ep.annual_volatility(x, period=periods))

    df['夏普'] = returns.apply(ep.sharpe_ratio, period=periods)

    df['最大回撤'] = returns.apply(lambda x: ep.max_drawdown(x))

    df['索提诺比率'] = returns.apply(lambda x: ep.sortino_ratio(x, period=periods))

    df['Calmar'] = returns.apply(lambda x: ep.calmar_ratio(x, period=periods))

    # 相对指标计算
    if mark_benchmark in returns.columns:

        select_col = [col for col in returns.columns if col != mark_benchmark]
        df['IR'] = returns[select_col].apply(
            lambda x: information_ratio(x, returns[mark_benchmark]))

        df['Alpha'] = returns[select_col].apply(
            lambda x: ep.alpha(x, returns[mark_benchmark], period=periods))

        df['Beta'] = returns[select_col].apply(
            lambda x: ep.beta(x, returns[mark_benchmark]))

        # 计算相对年化波动率
        df['超额收益率'] = df['年化收益率'] - \
            df.loc[mark_benchmark, '年化收益率']

    return df.T


# def show_worst_drawdown_periods(returns: pd.Series,
#                                 benchmark_code: str = "000300.SH",
#                                 top: int = 5):
#     """
#     Prints information about the worst drawdown periods.

#     Prints peak dates, valley dates, recovery dates, and net
#     drawdowns.

#     Parameters
#     ----------
#     returns : pd.Series
#         Daily returns of the strategy, noncumulative.
#          - See full explanation in tears.create_full_tear_sheet.
#     top : int, optional
#         Amount of top drawdowns periods to plot (default 5).
#     """

#     drawdown_df = ts.gen_drawdown_table(returns, top=top)
#     drawdown_df.index = list(range(1, len(drawdown_df) + 1))

#     phase_change = compare_phase_change(returns, benchmark_code, top)

#     df = pd.concat((drawdown_df, phase_change), axis=1)

#     # print_table(
#     #     df.sort_values('区间最大回撤 %', ascending=False),
#     #     name='序号',
#     #     float_format='{0:.2f}'.format,
#     # )

#     return df

# def compare_phase_change(returns: pd.Series,
#                          benchmark_code: str,
#                          top: int = 5) -> pd.DataFrame:
#     '''
#     对比策略与基准在回撤区间内的收益
#     ------
#         returns:策略净值收益率
#         benchmark_code:基准的代码
#     '''

#     beginDt = returns.index.min()
#     endDt = returns.index.max()

#     benchmark = get_wsd_data(benchmark_code,
#                              'pct_chg',
#                              beginDt,
#                              endDt,
#                              'priceAdj=B',
#                              usedf=True)

#     benchmark = benchmark['PCT_CHG'] / 100

#     df = pd.DataFrame(columns=['策略收益%', '基准收益%'],
#                       index=list(range(1, top + 1)))

#     drawdowns_list = ts.get_top_drawdowns(returns, top=top)

#     for i, v in enumerate(drawdowns_list):

#         peak_date, _, recovery_date = v

#         if pd.isnull(recovery_date):

#             df.loc[i + 1, '策略收益%'] = np.nan
#             df.loc[i + 1, '基准收益'] = np.nan

#         else:
#             df.loc[i + 1, '策略收益%'] = ep.cum_returns(
#                 returns.loc[peak_date:recovery_date]).iloc[-1]
#             df.loc[i + 1, '基准收益%'] = ep.cum_returns(
#                 benchmark.loc[peak_date:recovery_date])[-1]

#     return df
示例#27
0
def fin_funcs_port(df):
    """
    Financial calculations taken from Quantopians Empirical Library.
    :param df: dataframe containing daily returns calculated for a portfolio and as well for the related accounts.
    :return: Dictionary of financial ratios both for percent change returns and log returns.
    """
    returns_port = df["portfolio"]
    returns_acct = df["account"]

    risk_free_rate = 0.0

    annual_return_port = ep.annual_return(returns_port,
                                          period="daily",
                                          annualization=None)
    annual_return_acct = ep.annual_return(returns_acct,
                                          period="daily",
                                          annualization=None)

    cumm_return_port = ep.cum_returns(returns_port, starting_value=0).iloc[-1]
    cumm_return_acct = ep.cum_returns(returns_acct, starting_value=0).iloc[-1]

    cagr_port = ep.cagr(returns_port, period="daily", annualization=None)
    cagr_acct = ep.cagr(returns_acct, period="daily", annualization=None)

    sharpe_port = ep.sharpe_ratio(returns_port,
                                  risk_free=risk_free_rate,
                                  period="daily",
                                  annualization=None)
    sharpe_acct = ep.sharpe_ratio(returns_acct,
                                  risk_free=risk_free_rate,
                                  period="daily",
                                  annualization=None)

    annual_volatility_port = ep.annual_volatility(returns_port,
                                                  period="daily",
                                                  alpha=2.0,
                                                  annualization=None)
    annual_volatility_acct = ep.annual_volatility(returns_acct,
                                                  period="daily",
                                                  alpha=2.0,
                                                  annualization=None)
    max_drawdown_port = ep.max_drawdown(returns_port)
    max_drawdown_acct = ep.max_drawdown(returns_acct)

    calmar_port = ep.calmar_ratio(returns_port,
                                  period="daily",
                                  annualization=None)
    calmar_acct = ep.calmar_ratio(returns_acct,
                                  period="daily",
                                  annualization=None)

    sortino_port = ep.sortino_ratio(
        returns_port,
        required_return=0,
        period="daily",
        annualization=None,
        _downside_risk=None,
    )
    sortino_acct = ep.sortino_ratio(
        returns_acct,
        required_return=0,
        period="daily",
        annualization=None,
        _downside_risk=None,
    )

    tail_ratio_port = ep.tail_ratio(returns_port)
    tail_ratio_acct = ep.tail_ratio(returns_acct)

    financials = {
        ("return_portfolio", "annual_return"): annual_return_port,
        ("return_portfolio", "cumm_return"): cumm_return_port,
        ("return_portfolio", "cagr"): cagr_port,
        ("return_portfolio", "sharpe"): sharpe_port,
        ("return_portfolio", "annual_volatility"): annual_volatility_port,
        ("return_portfolio", "max_drawdown"): max_drawdown_port,
        ("return_portfolio", "calmar"): calmar_port,
        ("return_portfolio", "sortino"): sortino_port,
        ("return_portfolio", "tail_ratio"): tail_ratio_port,
        ("return_account", "annual_return"): annual_return_acct,
        ("return_account", "cumm_return"): cumm_return_acct,
        ("return_account", "cagr"): cagr_acct,
        ("return_account", "sharpe"): sharpe_acct,
        ("return_account", "annual_volatility"): annual_volatility_acct,
        ("return_account", "max_drawdown"): max_drawdown_acct,
        ("return_account", "calmar"): calmar_acct,
        ("return_account", "sortino"): sortino_acct,
        ("return_account", "tail_ratio"): tail_ratio_acct,
    }

    return financials
                                 span=60,
                                 min_periods=0).std(bias=False)
df['return'] = AD1.iloc[7479:, 0] * y_pred_lstm * 0.15 / day_vol

#%%
import empyrical

print("Annualized Sharpe Ratio = ",
      empyrical.sharpe_ratio(df['return'], period='daily'))
print("Annualized Mean Returns = ",
      empyrical.annual_return(df['return'], period='daily'))
print("Annualized Standard Deviations = ",
      empyrical.annual_volatility(df['return'], period='daily'))
print("Max Drawdown (MDD) = ", empyrical.max_drawdown(df['return']))
print("Sortino ratio = ", empyrical.sortino_ratio(df['return'],
                                                  period='daily'))
print("Calmar ratio = ", empyrical.calmar_ratio(df['return'], period='daily'))

#%%
a = pd.DataFrame()
a = pd.concat([a, TSMOM.ind_return['port_avg']], axis=1)
a = a.tail(831)
b = empyrical.cum_returns(a)
c = empyrical.cum_returns(df['return'])
plt.plot(b, color='red', label='R')
plt.plot(c, color='blue', label='R')
plt.title('Cumulative return in daily basis')
plt.xlabel('Time')
plt.ylabel('Cumulative return')
plt.legend()
plt.show()
示例#29
0
def calmar_ratio(portfolio_daily_returns):
    return ep.calmar_ratio(portfolio_daily_returns)
示例#30
0
def fin_funcs(df):
    """
    Financial calculations taken from Quantopians Empirical Library.

    :param df: dataframe containing daily returns calculated on a percentage change and also by log scale.
    :return: Dictionary of financial ratios both for percent change returns and log returns.
    """
    returns_pct = df["pct_change"]

    risk_free_rate = 0.0

    annual_return_pct = ep.annual_return(returns_pct,
                                         period="daily",
                                         annualization=None)
    cumm_return_pct = ep.cum_returns(returns_pct, starting_value=0).iloc[-1]
    cagr_pct = ep.cagr(returns_pct, period="daily", annualization=None)
    sharpe_pct = ep.sharpe_ratio(returns_pct,
                                 risk_free=risk_free_rate,
                                 period="daily",
                                 annualization=None)
    annual_volatility_pct = ep.annual_volatility(returns_pct,
                                                 period="daily",
                                                 alpha=2.0,
                                                 annualization=None)
    max_drawdown_pct = ep.max_drawdown(returns_pct)
    calmar_pct = ep.calmar_ratio(returns_pct,
                                 period="daily",
                                 annualization=None)
    sortino_pct = ep.sortino_ratio(
        returns_pct,
        required_return=0,
        period="daily",
        annualization=None,
        _downside_risk=None,
    )
    tail_ratio_pct = ep.tail_ratio(returns_pct)

    financials = {
        "annual_return": annual_return_pct,
        "cumm_return": cumm_return_pct,
        "cagr": cagr_pct,
        "sharpe": sharpe_pct,
        "annual_volatility": annual_volatility_pct,
        "max_drawdown": max_drawdown_pct,
        "calmar": calmar_pct,
        "sortino": sortino_pct,
        "tail_ratio": tail_ratio_pct,
    }

    # Originally set up program to analyse both pct_change and log returns, but the difference between log and
    # pct_change was not material to the final analysis. Consequently pct_change used exclusively. The code below
    # is left in tact should log returns at the account level be desired.

    # returns_log = df["log_ret"]
    # Log returns not used in final scenario.
    # annual_return_log = ep.annual_return(
    #     returns_log, period="daily", annualization=None
    # )
    # cumm_return_log = ep.cum_returns(returns_log, starting_value=0).iloc[-1]
    # cagr_log = ep.cagr(returns_log, period="daily", annualization=None)
    # sharpe_log = ep.sharpe_ratio(
    #     returns_log, risk_free=risk_free_rate, period="daily", annualization=None
    # )
    # annual_volatility_log = ep.annual_volatility(
    #     returns_log, period="daily", alpha=2.0, annualization=None
    # )
    # max_drawdown_log = ep.max_drawdown(returns_log)
    # calmar_log = ep.calmar_ratio(returns_log, period="daily", annualization=None)
    # sortino_log = ep.sortino_ratio(
    #     returns_log,
    #     required_return=0,
    #     period="daily",
    #     annualization=None,
    #     _downside_risk=None,
    # )
    # tail_ratio_log = ep.tail_ratio(returns_log)

    # financials = {
    #     ("return_percent_change", "annual_return"): annual_return_pct,
    #     ("return_percent_change", "cumm_return"): cumm_return_pct,
    #     ("return_percent_change", "cagr"): cagr_pct,
    #     ("return_percent_change", "sharpe"): sharpe_pct,
    #     ("return_percent_change", "annual_volatility"): annual_volatility_pct,
    #     ("return_percent_change", "max_drawdown"): max_drawdown_pct,
    #     ("return_percent_change", "calmar"): calmar_pct,
    #     ("return_percent_change", "sortino"): sortino_pct,
    #     ("return_percent_change", "tail_ratio"): tail_ratio_pct,
    #     ("return_log", "annual_return"): annual_return_log,
    #     ("return_log", "cumm_return"): cumm_return_log,
    #     ("return_log", "cagr"): cagr_log,
    #     ("return_log", "sharpe"): sharpe_log,
    #     ("return_log", "annual_volatility"): annual_volatility_log,
    #     ("return_log", "max_drawdown"): max_drawdown_log,
    #     ("return_log", "calmar"): calmar_log,
    #     ("return_log", "sortino"): sortino_log,
    #     ("return_log", "tail_ratio"): tail_ratio_log,
    #     }

    return financials
示例#31
0
def work(PARAMS):
    info('work %s' % str(PARAMS))
    stock_df_dict = None
    show_df = None
    order_df = None
    PROPERTY = None
    STRATEGY = PARAMS[0]
    POS = PARAMS[1]
    N = PARAMS[2]
    K = PARAMS[3]
    M = PARAMS[4]
    global ROTATION_LIST
    ROTATION_LIST = ROTATION_LIST

    stock_df_dict = get_stock_df_dict(N, M)
    show_df, order_df, PROPERTY = run_turtle(ROTATION_LIST, stock_df_dict, STRATEGY, POS, N, K, M)

    df = show_df.dropna(how='any', inplace=False).copy()
    df = df.loc[start_date:end_date]
    algo = df['PROPERTY'].pct_change()
    benchmark = df.open.pct_change()

    DAYS_ALL = len(df)
    DAYS_NOFULLHOLD = len(df[df['CASH'] > (df['PROPERTY'] / POS)])

    output_str = ''
    for y in range(int(start_date.split('-')[0]), int(end_date.split('-')[0]) + 1, 1):
        # info('y = %d' % y)
        y_df = df.loc['%d-01-01' % y:'%d-01-01' % (y + 1)]
        if len(y_df) == 0:
            continue
        y_algo = y_df['PROPERTY'].pct_change()
        # info(y_algo)
        y_benchmark = y_df.open.pct_change()
        # info('y_benc')
        result = '%d-%d,%.3f,%.3f,%.3f,%.3f' % (
            y, y + 1, emp.cum_returns(y_algo)[-1], emp.cum_returns(y_benchmark)[-1], emp.max_drawdown(y_algo), emp.max_drawdown(y_benchmark)
        )
        output_str += result
        output_str += ';'
    # info(output_str)

    df = order_df.copy()
    df['pro_pct'] = (df.borrow_price - df.return_price) / df.return_price
    df = df.loc[:, ['symbol', 'pro_pct']]
    df = df.groupby(by='symbol').sum()
    buy_stock_count = len(df)

    score_sr = pd.Series({
        'START': start_date,
        'END': end_date,
        'STRATEGY': STRATEGY,
        'POS': POS,
        'N': N,
        'K': K,
        'M': M,
        'ORDER': len(order_df),
        'STOCK': buy_stock_count,
        'RETURN_ALGO': emp.cum_returns(algo)[-1],
        'RETURN_BENC': emp.cum_returns(benchmark)[-1],
        'MAXDROPDOWN_ALGO': emp.max_drawdown(algo),
        'MAXDROPDOWN_BENC': emp.max_drawdown(benchmark),
        'WINRATE_ORDER': len(order_df[order_df.profit > 0]) / len(order_df[order_df.profit != 0]),
        'WINRATE_YEARLY': 0,
        'ANNUAL_RETURN': emp.annual_return(algo),
        'ANNUAL_VOLATILITY': emp.annual_volatility(algo, period='daily'),
        'CALMAR_RATIO': emp.calmar_ratio(algo),
        'SHARPE_RATIO': emp.sharpe_ratio(returns=algo),
        'ALPHA': emp.alpha(returns=algo, factor_returns=benchmark, risk_free=0.00),
        'BETA': emp.beta(returns=algo, factor_returns=benchmark, risk_free=0.00),
        'DAYS_ALL': DAYS_ALL,
        'DAYS_NOFULLHOLD': DAYS_NOFULLHOLD,
        'RET_PER_YEAR': output_str,
    })

    YEAR_COUNT = 0
    ALGO_WIN_YEAR_COUNT = 0
    df = show_df.dropna(how='any', inplace=False).copy()
    df = df.loc[start_date:end_date]
    for y in range(int(start_date.split('-')[0]), int(end_date.split('-')[0]) + 1, 1):
        y_df = df.loc['%d-01-01' % y:'%d-01-01' % (y + 1)]
        # info('y = %d' % y)
        if len(y_df) == 0:
            continue
        y_algo = y_df['PROPERTY'].pct_change()
        y_benchmark = y_df.open.pct_change()
        score_sr['RETURN_ALGO_%d' % y] = emp.cum_returns(y_algo)[-1]
        score_sr['RETURN_BENC_%d' % y] = emp.cum_returns(y_benchmark)[-1]
        YEAR_COUNT += 1
        if score_sr['RETURN_ALGO_%d' % y] > score_sr['RETURN_BENC_%d' % y]:
            ALGO_WIN_YEAR_COUNT += 1

    score_sr['WINRATE_YEARLY'] = ALGO_WIN_YEAR_COUNT / YEAR_COUNT

    return PARAMS, score_sr, order_df