Skip to content

Instantly share code, notes, and snippets.

@marcosan93
Created April 15, 2022 23:09
Show Gist options
  • Save marcosan93/0819a8bb5960f34e6219562703b331f8 to your computer and use it in GitHub Desktop.
Save marcosan93/0819a8bb5960f34e6219562703b331f8 to your computer and use it in GitHub Desktop.
def riskAnalysis(performance, prices, price_history, interval_width):
"""
Analyzes the performance DataFrame to calculate various
evaluation metrics on the backtest to determine if
the backtest performance was favorable.
"""
### Hypothesis testing average returns
# Weekly returns for fb prophet
rets = performance['fbp_positions'].pct_change(5).dropna()
# Buy and hold for about the last two years for the stock
hold = price_history['Close'].tail(500).apply(np.log).diff().cumsum().apply(np.exp).dropna()
# Weekly returns in those years
hold_ret = hold.pct_change(5).mean()
# Average returns
if len(performance)<=30:
# T-testing
stat_test = stats.ttest_1samp(
rets,
popmean=hold_ret
)
else:
# Z-testing
stat_test = ztest(
rets,
value=hold_ret
)
# Ending portfolio balance
bal = performance.tail(1)
# Moving Average returns
ma_ret = performance.rolling(window=5).mean().dropna()
# How often fbp beats holding
ma_ret['diff'] = ma_ret['fbp_positions'] > ma_ret['buy_hold']
diff = ma_ret['diff'].mean()
# How often the fbp portfolio had a balance greater than its initial balance
ma_ret['beat_bal'] = ma_ret['fbp_positions'] > 1
beat_bal = ma_ret['beat_bal'].mean()
# How often fbp MA returns were positive
ma_ret['uptrend'] = ma_ret['fbp_positions'].diff().dropna()>=0
uptrend = ma_ret['uptrend'].mean()
# Performance score
score = 0
# P-value check
if stat_test[1]<0.05:
score += 1
# Checking ending portfolio balance
if bal['fbp_positions'][0]>bal['buy_hold'][0] and bal['fbp_positions'][0]>1:
score += 1
# How often fbp outperformed buy and hold
if diff>.8:
score += 1
# How often fbp had returns greater than the initial portfolio balance
if beat_bal>.6:
score += 1
# How often fbp had positive upward trend
if uptrend>.55:
score += 1
# Dictionary containing values
score_res = {
"result": True,
"score": score,
"endingBalance": {
"prophet": bal['fbp_positions'][0],
"buyHold": bal['buy_hold'][0]
},
"betterThanBuyHold": diff,
"greaterPortfolioBalance": beat_bal,
"upwardTrend": uptrend,
"pValue": stat_test[1],
"interval_width": interval_width
}
if score>=5:
return score_res
else:
# Backtest result is bad
score_res['result'] = False
return score_res
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment