qis 3.1.6__tar.gz → 3.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qis-3.1.6 → qis-3.2.1}/PKG-INFO +1 -1
- {qis-3.1.6 → qis-3.2.1}/pyproject.toml +1 -1
- {qis-3.1.6 → qis-3.2.1}/qis/examples/bootstrap_analysis.py +1 -1
- {qis-3.1.6 → qis-3.2.1}/qis/examples/ohlc_vol_analysis.py +7 -7
- {qis-3.1.6 → qis-3.2.1}/qis/examples/simulate_quant_strats.py +1 -1
- {qis-3.1.6 → qis-3.2.1}/qis/examples/vol_without_weekends.py +2 -2
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/ewm.py +20 -28
- {qis-3.1.6 → qis-3.2.1}/qis/models/stats/ohlc_vol.py +4 -4
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/regime_classifier.py +1 -1
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/timeseries_bfill.py +3 -3
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/ewm_portfolio_risk.py +4 -4
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/multi_portfolio_data.py +5 -5
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/strats/quant_strats_delta1.py +1 -1
- {qis-3.1.6 → qis-3.2.1}/qis/settings.yaml +2 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/dates.py +2 -2
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_ops.py +3 -3
- {qis-3.1.6 → qis-3.2.1}/LICENSE.txt +0 -0
- {qis-3.1.6 → qis-3.2.1}/README.md +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/best_returns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/bond_futures_portfolio.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/boxplot_conditional_returns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/btc_asset_corr.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/constant_notional.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/constant_weight_portfolios.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/core/perf_bbg_prices.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/core/price_plots.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/core/us_election.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/credit_spreads.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/credit_trackers.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/europe_futures.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/factsheets/multi_assets.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/factsheets/multi_strategy.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/factsheets/pyblogs_reports.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/factsheets/strategy.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/factsheets/strategy_benchmark.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/generate_option_rolls.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/interpolation_infrequent_returns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/leveraged_strategies.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/long_short.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/momentum_indices.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/overnight_returns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/perf_external_assets.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/perp_pricing.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/readme_performances.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/risk_return_frontier.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/rolling_performance.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/seasonality.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/sharpe_vs_sortino.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/test_ewm.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/test_scatter.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/try_pybloqs.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/universe_corrs.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/vix_conditional_returns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/vix_spy_by_year.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/examples/vix_tenor_analysis.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/file_utils.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/local_path.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/README.md +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/auto_corr.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/corr_cov_matrix.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/ewm_convolution.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/ewm_factors.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/ewm_winsor_outliers.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/pca.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/plot_correlations.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/linear/ra_returns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/stats/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/stats/bootstrap.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/stats/rolling_stats.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/models/stats/test_bootstrap.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/README.md +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/cond_regression.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/config.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/desc_table.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/fx_ops.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/perf_stats.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/perfstats/returns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/README.md +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/bars.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/boxplot.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/contour.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/data_timeseries.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/desc_table.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/drawdowns.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/perf_table.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/prices.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/regime_class_table.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/regime_data.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/regime_pdf.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/regime_scatter.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/returns_heatmap.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/derived/returns_scatter.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/errorbar.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/heatmap.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/histogram.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/histplot2d.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/lineplot.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/pie.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/qqplot.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/reports/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/reports/econ_data_single.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/reports/gantt_data_history.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/reports/price_history.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/reports/utils.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/scatter.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/stackplot.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/table.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/time_series.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/plots/utils.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/README.md +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/backtester.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/portfolio_data.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/brinson_attribution.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/config.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/multi_assets_factsheet.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/multi_strategy_factsheet.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/strategy_benchmark_factsheet.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/strategy_factsheet.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/strats/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/portfolio/strats/seasonal_strats.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/sql_engine.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/test_data.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/README.md +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/__init__.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_agg.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_cut.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_freq.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_groups.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_melt.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_str.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_to_scores.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/df_to_weights.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/generic.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/np_ops.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/ols.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/sampling.py +0 -0
- {qis-3.1.6 → qis-3.2.1}/qis/utils/struct_ops.py +0 -0
{qis-3.1.6 → qis-3.2.1}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qis
|
3
|
-
Version: 3.1
|
3
|
+
Version: 3.2.1
|
4
4
|
Summary: Implementation of visualisation and reporting analytics for Quantitative Investment Strategies
|
5
5
|
License: LICENSE.txt
|
6
6
|
Keywords: quantitative,investing,portfolio optimization,systematic strategies,volatility
|
@@ -52,7 +52,7 @@ def plot_bootsrap_paths(prices: pd.Series,
|
|
52
52
|
span = np.maximum(block_size, 5)
|
53
53
|
ewma_vols = qis.compute_ewm_vol(data=log_returns,
|
54
54
|
span=span,
|
55
|
-
|
55
|
+
annualization_factor=252)
|
56
56
|
with sns.axes_style("darkgrid"):
|
57
57
|
fig, ax = plt.subplots(1, 1, figsize=(10, 7))
|
58
58
|
qis.set_suptitle(fig, title=f"EWMA-{span} span volatility of realized (red) and bootsrapped paths (gray)")
|
@@ -49,7 +49,7 @@ def fetch_hf_ohlc(ticker: str = 'SPY',
|
|
49
49
|
|
50
50
|
def estimate_hf_vol(ticker: str = 'SPY',
|
51
51
|
agg_freq: str = 'B',
|
52
|
-
|
52
|
+
annualization_factor: float = 260,
|
53
53
|
freqs: List[str] = ['1d', '1h', '30m', '15m', '5m'],
|
54
54
|
ohlc_estimator_type: OhlcEstimatorType = OhlcEstimatorType.PARKINSON
|
55
55
|
) -> pd.DataFrame:
|
@@ -60,20 +60,20 @@ def estimate_hf_vol(ticker: str = 'SPY',
|
|
60
60
|
vols[freq] = qis.estimate_hf_ohlc_vol(ohlc_data=ohlc_data,
|
61
61
|
ohlc_estimator_type=ohlc_estimator_type,
|
62
62
|
agg_freq=agg_freq,
|
63
|
-
|
63
|
+
annualization_factor=annualization_factor*AF_MULTIPLIERS[freq])
|
64
64
|
vols = pd.DataFrame.from_dict(vols, orient='columns').dropna()
|
65
65
|
return vols
|
66
66
|
|
67
67
|
|
68
68
|
def plot_hf_vols(ticker: str = 'SPY',
|
69
69
|
agg_freq: str = 'B',
|
70
|
-
|
70
|
+
annualization_factor: float = 260,
|
71
71
|
freqs: List[str] = ['1d', '1h', '30m', '15m', '5m'],
|
72
72
|
ohlc_estimator_type: OhlcEstimatorType = OhlcEstimatorType.PARKINSON
|
73
73
|
):
|
74
74
|
vols = estimate_hf_vol(ticker=ticker,
|
75
75
|
agg_freq=agg_freq,
|
76
|
-
|
76
|
+
annualization_factor=annualization_factor,
|
77
77
|
freqs=freqs,
|
78
78
|
ohlc_estimator_type=ohlc_estimator_type)
|
79
79
|
|
@@ -101,13 +101,13 @@ def run_unit_test(unit_test: UnitTests):
|
|
101
101
|
|
102
102
|
elif unit_test == UnitTests.HF_VOL:
|
103
103
|
# use small number of num_samples for illustration
|
104
|
-
df = estimate_hf_vol(ticker='SPY', agg_freq='B',
|
104
|
+
df = estimate_hf_vol(ticker='SPY', agg_freq='B', annualization_factor=260)
|
105
105
|
print(df)
|
106
106
|
df.plot()
|
107
107
|
|
108
108
|
elif unit_test == UnitTests.PLOT_HF_VOL:
|
109
|
-
# plot_hf_vols(ticker='SPY', agg_freq='B',
|
110
|
-
plot_hf_vols(ticker='ETH-USD', agg_freq='D',
|
109
|
+
# plot_hf_vols(ticker='SPY', agg_freq='B', annualization_factor=260)
|
110
|
+
plot_hf_vols(ticker='ETH-USD', agg_freq='D', annualization_factor=365,
|
111
111
|
ohlc_estimator_type=OhlcEstimatorType.CLOSE_TO_CLOSE)
|
112
112
|
|
113
113
|
plt.show()
|
@@ -107,7 +107,7 @@ def plot_strategies_prices(nav_data: pd.DataFrame,
|
|
107
107
|
) -> None:
|
108
108
|
|
109
109
|
nav_returns = qis.to_returns(prices=nav_data)
|
110
|
-
eod_ewm_vol = qis.compute_ewm_vol(data=nav_returns, span=vol_span, mean_adj_type=qis.MeanAdjType.NONE,
|
110
|
+
eod_ewm_vol = qis.compute_ewm_vol(data=nav_returns, span=vol_span, mean_adj_type=qis.MeanAdjType.NONE, annualization_factor=vol_af)
|
111
111
|
|
112
112
|
# trim plot data
|
113
113
|
nav_data = time_period.locate(nav_data)
|
@@ -30,10 +30,10 @@ def compute_vols(prices: pd.Series,
|
|
30
30
|
"""
|
31
31
|
returns = np.log(prices).diff(1)
|
32
32
|
init_value = np.nanvar(returns, axis=0) # set initial value to average variance
|
33
|
-
vol = qis.compute_ewm_vol(data=returns, span=span,
|
33
|
+
vol = qis.compute_ewm_vol(data=returns, span=span, annualization_factor=365*24, init_value=init_value)
|
34
34
|
|
35
35
|
returns1 = returns.where(returns.index.dayofweek < 5, other=np.nan)
|
36
|
-
vol1 = qis.compute_ewm_vol(data=returns1, span=span,
|
36
|
+
vol1 = qis.compute_ewm_vol(data=returns1, span=span, annualization_factor=260*24, init_value=init_value)
|
37
37
|
vols = pd.concat([vol.rename('including weekends'),
|
38
38
|
vol1.rename('excluding weekends')], axis=1)
|
39
39
|
return vols
|
@@ -598,7 +598,7 @@ def compute_ewm_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
|
|
598
598
|
init_value: Optional[Union[float, np.ndarray]] = None,
|
599
599
|
apply_sqrt: bool = True,
|
600
600
|
annualize: bool = False,
|
601
|
-
|
601
|
+
annualization_factor: Optional[float] = None,
|
602
602
|
vol_floor_quantile: Optional[float] = None, # to floor the volatility = 0.16
|
603
603
|
vol_floor_quantile_roll_period: int = 5*260, # 5y for daily returns
|
604
604
|
warmup_period: Optional[int] = None,
|
@@ -644,14 +644,14 @@ def compute_ewm_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
|
|
644
644
|
if warmup_period is not None: # set to nan first nonnan in warmup_period
|
645
645
|
ewm = npo.set_nans_for_warmup_period(a=ewm, warmup_period=warmup_period)
|
646
646
|
|
647
|
-
if annualize or
|
648
|
-
if
|
647
|
+
if annualize or annualization_factor is not None:
|
648
|
+
if annualization_factor is None:
|
649
649
|
if isinstance(data, pd.DataFrame) or isinstance(data, pd.Series):
|
650
|
-
|
650
|
+
annualization_factor = da.infer_an_from_data(data=data)
|
651
651
|
else:
|
652
652
|
warnings.warn(f"in compute_ewm annualization_factor for np array default is 1")
|
653
|
-
|
654
|
-
ewm =
|
653
|
+
annualization_factor = 1.0
|
654
|
+
ewm = annualization_factor * ewm
|
655
655
|
|
656
656
|
if apply_sqrt:
|
657
657
|
ewm = np.sqrt(ewm)
|
@@ -672,7 +672,7 @@ def compute_ewm_newey_west_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
|
|
672
672
|
init_value: Optional[Union[float, np.ndarray]] = None,
|
673
673
|
apply_sqrt: bool = True,
|
674
674
|
annualize: bool = False,
|
675
|
-
|
675
|
+
annualization_factor: Optional[float] = None,
|
676
676
|
warmup_period: Optional[int] = None,
|
677
677
|
nan_backfill: NanBackfill = NanBackfill.FFILL
|
678
678
|
) -> Union[pd.DataFrame, pd.Series, np.ndarray]:
|
@@ -703,35 +703,27 @@ def compute_ewm_newey_west_vol(data: Union[pd.DataFrame, pd.Series, np.ndarray],
|
|
703
703
|
if isinstance(init_value, np.ndarray):
|
704
704
|
init_value = float(init_value)
|
705
705
|
|
706
|
-
|
706
|
+
ewm = ewm_recursion(a=np.square(a), ewm_lambda=ewm_lambda, init_value=init_value, nan_backfill=nan_backfill)
|
707
707
|
|
708
|
-
|
709
|
-
|
710
|
-
ewms = {}
|
711
|
-
for m in np.arange(num_lags):
|
708
|
+
# compute m recursions
|
709
|
+
for m in np.arange(1, num_lags):
|
712
710
|
# lagged value
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
a_m[:m] = np.nan
|
719
|
-
ewms[m] = ewm_recursion(a=a*a_m, ewm_lambda=ewm_lambda, init_value=init_value, nan_backfill=nan_backfill)
|
720
|
-
|
721
|
-
ewm_
|
722
|
-
|
723
|
-
|
711
|
+
a_m = np.empty_like(a)
|
712
|
+
a_m[m:] = a[:-m]
|
713
|
+
a_m[:m] = np.nan
|
714
|
+
ewm_m = ewm_recursion(a=a*a_m, ewm_lambda=ewm_lambda, init_value=init_value, nan_backfill=nan_backfill)
|
715
|
+
ewm += (1.0-m/(num_lags+1))*ewm_m
|
724
716
|
if warmup_period is not None: # set to nan first nonnan in warmup_period
|
725
717
|
ewm = npo.set_nans_for_warmup_period(a=ewm, warmup_period=warmup_period)
|
726
718
|
|
727
|
-
if annualize or
|
728
|
-
if
|
719
|
+
if annualize or annualization_factor is not None:
|
720
|
+
if annualization_factor is None:
|
729
721
|
if isinstance(data, pd.DataFrame) or isinstance(data, pd.Series):
|
730
|
-
|
722
|
+
annualization_factor = da.infer_an_from_data(data=data)
|
731
723
|
else:
|
732
724
|
warnings.warn(f"in compute_ewm annualization_factor for np array default is 1")
|
733
|
-
|
734
|
-
ewm =
|
725
|
+
annualization_factor = 1.0
|
726
|
+
ewm = annualization_factor * ewm
|
735
727
|
|
736
728
|
if apply_sqrt:
|
737
729
|
ewm = np.sqrt(ewm)
|
@@ -56,7 +56,7 @@ def estimate_ohlc_var(ohlc_data: pd.DataFrame, # must contain ohlc columnes
|
|
56
56
|
|
57
57
|
def estimate_hf_ohlc_vol(ohlc_data: pd.DataFrame,
|
58
58
|
ohlc_estimator_type: OhlcEstimatorType = OhlcEstimatorType.PARKINSON,
|
59
|
-
|
59
|
+
annualization_factor: float = None, # annualisation factor highly recomended
|
60
60
|
is_exclude_weekends: bool = False, # for crypto
|
61
61
|
agg_freq: Optional[str] = 'B'
|
62
62
|
) -> pd.Series:
|
@@ -69,10 +69,10 @@ def estimate_hf_ohlc_vol(ohlc_data: pd.DataFrame,
|
|
69
69
|
if agg_freq is not None:
|
70
70
|
sample_var = sample_var.resample(agg_freq).mean()
|
71
71
|
|
72
|
-
if
|
73
|
-
|
72
|
+
if annualization_factor is None:
|
73
|
+
annualization_factor = qis.infer_an_from_data(data=sample_var)
|
74
74
|
|
75
|
-
vols = np.sqrt(
|
75
|
+
vols = np.sqrt(annualization_factor*sample_var)
|
76
76
|
if is_exclude_weekends:
|
77
77
|
vols = vols[vols.index.dayofweek < 5]
|
78
78
|
return vols
|
@@ -41,7 +41,7 @@ def compute_regime_avg(sampled_returns_with_regime_id: pd.DataFrame,
|
|
41
41
|
|
42
42
|
"""
|
43
43
|
compute conditional means by the regime ids
|
44
|
-
compute normalized prices attributions =
|
44
|
+
compute normalized prices attributions = annualization_factor*freq*cvar
|
45
45
|
"""
|
46
46
|
# compute mean by regimes
|
47
47
|
regime_means, norm_q = compute_mean_freq_regimes(sampled_returns_with_regime_id=sampled_returns_with_regime_id)
|
@@ -17,7 +17,7 @@ import qis.models.linear.ewm as ewm
|
|
17
17
|
def interpolate_infrequent_returns(infrequent_returns: Union[pd.Series, pd.DataFrame],
|
18
18
|
pivot_returns: pd.Series,
|
19
19
|
span: int = 12,
|
20
|
-
|
20
|
+
annualization_factor: float = 260,
|
21
21
|
is_to_log_returns: bool = False,
|
22
22
|
vol_adjustment: float = 1.15 # adjust vol of the bridge
|
23
23
|
) -> Union[pd.Series, pd.DataFrame]:
|
@@ -32,7 +32,7 @@ def interpolate_infrequent_returns(infrequent_returns: Union[pd.Series, pd.DataF
|
|
32
32
|
infrequent_return_backfills[column] = interpolate_infrequent_returns(infrequent_returns=ds,
|
33
33
|
pivot_returns=pivot_returns,
|
34
34
|
span=span,
|
35
|
-
|
35
|
+
annualization_factor=annualization_factor,
|
36
36
|
is_to_log_returns=is_to_log_returns,
|
37
37
|
vol_adjustment=vol_adjustment)
|
38
38
|
infrequent_return_backfills = pd.DataFrame.from_dict(infrequent_return_backfills, orient='columns')
|
@@ -55,7 +55,7 @@ def interpolate_infrequent_returns(infrequent_returns: Union[pd.Series, pd.DataF
|
|
55
55
|
pivot_brownian = (pivot_brownian - np.nanmean(pivot_brownian)) / np.nanstd(pivot_brownian) # path to (0, 1) brownian
|
56
56
|
|
57
57
|
# add running times
|
58
|
-
seconds_per_year =
|
58
|
+
seconds_per_year = annualization_factor * 24 * 60 * 60 # days, hours, minute, seconds
|
59
59
|
t = pd.Series((infrequent_returns.index - date0).total_seconds() / seconds_per_year, index=infrequent_returns.index)
|
60
60
|
t1 = t.shift(-1)
|
61
61
|
dt = t1 - t
|
@@ -25,15 +25,15 @@ VAR99_SCALER_BP = VAR99 * 10000
|
|
25
25
|
def limit_weights_to_max_var_limit(weights: np.ndarray,
|
26
26
|
vols: np.ndarray,
|
27
27
|
max_var_limit_bp: Union[np.ndarray, float] = 25.00,
|
28
|
-
|
28
|
+
annualization_factor: float = 260
|
29
29
|
) -> np.ndarray:
|
30
30
|
"""
|
31
31
|
limit weights to max weight_max_var_bp
|
32
|
-
use: var = 2.33 * abs(weight) * vols_annualised / sqrt(
|
33
|
-
then abs(weight) <= weight_max_var_limit_bp / (VAR99_SCALER_BP * vols_annualised / sqrt(
|
32
|
+
use: var = 2.33 * abs(weight) * vols_annualised / sqrt(annualization_factor)
|
33
|
+
then abs(weight) <= weight_max_var_limit_bp / (VAR99_SCALER_BP * vols_annualised / sqrt(annualization_factor))
|
34
34
|
vols are annualised vols
|
35
35
|
"""
|
36
|
-
saf = np.sqrt(
|
36
|
+
saf = np.sqrt(annualization_factor)
|
37
37
|
instrument_var = VAR99_SCALER_BP * np.abs(weights) * vols / saf
|
38
38
|
cond = instrument_var > max_var_limit_bp
|
39
39
|
if np.any(cond):
|
@@ -220,7 +220,7 @@ class MultiPortfolioData:
|
|
220
220
|
benchmark_idx: int = 1,
|
221
221
|
freq: Optional[str] = 'B',
|
222
222
|
time_period: TimePeriod = None,
|
223
|
-
|
223
|
+
annualization_factor: float = 260,
|
224
224
|
is_unit_based_traded_volume: bool = True,
|
225
225
|
**kwargs
|
226
226
|
) -> pd.DataFrame:
|
@@ -266,10 +266,10 @@ class MultiPortfolioData:
|
|
266
266
|
|
267
267
|
tre_table = pd.concat([total_diff, tre,
|
268
268
|
total_strategy_perf, total_benchmark_perf,
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
269
|
+
annualization_factor * strategy_turnover.mean(0).rename(f"{strategy_ticker} an turnover"),
|
270
|
+
annualization_factor * benchmark_turnover.mean(0).rename(f"{benchmark_ticker} an turnover"),
|
271
|
+
annualization_factor * strategy_cost.mean(0).rename(f"{strategy_ticker} an cost"),
|
272
|
+
annualization_factor * benchmark_cost.mean(0).rename(f"{benchmark_ticker} an cost"),
|
273
273
|
], axis=1)
|
274
274
|
|
275
275
|
return tre_table
|
@@ -24,7 +24,7 @@ def simulate_vol_target_strats(prices: Union[pd.DataFrame, pd.Series],
|
|
24
24
|
ewm_vol = ewm.compute_ewm_vol(data=log_returns,
|
25
25
|
span=vol_span,
|
26
26
|
mean_adj_type=ewm.MeanAdjType.NONE,
|
27
|
-
|
27
|
+
annualization_factor=vol_af)
|
28
28
|
# vol target weights
|
29
29
|
weights_100 = qu.to_finite_reciprocal(data=ewm_vol, fill_value=0.0, is_gt_zero=True)
|
30
30
|
nav_weights = weights_100.multiply(vol_target)
|
@@ -46,12 +46,12 @@ def get_current_time_with_tz(tz: Optional[str] = 'UTC',
|
|
46
46
|
def get_time_to_maturity(maturity_time: pd.Timestamp,
|
47
47
|
value_time: pd.Timestamp,
|
48
48
|
is_floor_at_zero: bool = True,
|
49
|
-
|
49
|
+
annualization_factor: float = 365
|
50
50
|
) -> float:
|
51
51
|
"""
|
52
52
|
return annualised difference between mat_date and value_time
|
53
53
|
"""
|
54
|
-
seconds_per_year =
|
54
|
+
seconds_per_year = annualization_factor * 24 * 60 * 60 # days, hours, minute, seconds
|
55
55
|
ttm = (maturity_time - value_time).total_seconds() / seconds_per_year
|
56
56
|
if is_floor_at_zero and ttm < 0.0:
|
57
57
|
ttm = 0.0
|
@@ -312,7 +312,7 @@ def multiply_df_by_dt(df: Union[pd.DataFrame, pd.Series],
|
|
312
312
|
dates: Union[pd.DatetimeIndex, pd.Index] = None,
|
313
313
|
lag: Optional[int] = None,
|
314
314
|
is_actual_calendar_dt: bool = True,
|
315
|
-
|
315
|
+
annualization_factor: float = 365.0
|
316
316
|
) -> Union[pd.DataFrame, pd.Series]:
|
317
317
|
"""
|
318
318
|
to compute rate adjustment with data - rate:
|
@@ -336,9 +336,9 @@ def multiply_df_by_dt(df: Union[pd.DataFrame, pd.Series],
|
|
336
336
|
# apply dt multiplication
|
337
337
|
if len(df.index) > 1:
|
338
338
|
if is_actual_calendar_dt:
|
339
|
-
delta = np.append(0.0, (df.index[1:] - df.index[:-1]).days /
|
339
|
+
delta = np.append(0.0, (df.index[1:] - df.index[:-1]).days / annualization_factor)
|
340
340
|
else:
|
341
|
-
delta = 1.0 /
|
341
|
+
delta = 1.0 / annualization_factor
|
342
342
|
df = df.multiply(delta, axis=0)
|
343
343
|
else:
|
344
344
|
warnings.warn(f"in adjust_data_with_dt: lengh of data index is one - cannot adjust by dt")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|