qis 3.0.7__tar.gz → 3.0.8__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.
Files changed (150) hide show
  1. {qis-3.0.7 → qis-3.0.8}/PKG-INFO +1 -1
  2. {qis-3.0.7 → qis-3.0.8}/pyproject.toml +1 -1
  3. {qis-3.0.7 → qis-3.0.8}/qis/plots/time_series.py +20 -19
  4. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/brinson_attribution.py +1 -1
  5. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/strategy_benchmark_factsheet.py +9 -4
  6. {qis-3.0.7 → qis-3.0.8}/LICENSE.txt +0 -0
  7. {qis-3.0.7 → qis-3.0.8}/README.md +0 -0
  8. {qis-3.0.7 → qis-3.0.8}/qis/__init__.py +0 -0
  9. {qis-3.0.7 → qis-3.0.8}/qis/examples/best_returns.py +0 -0
  10. {qis-3.0.7 → qis-3.0.8}/qis/examples/bond_futures_portfolio.py +0 -0
  11. {qis-3.0.7 → qis-3.0.8}/qis/examples/bootstrap_analysis.py +0 -0
  12. {qis-3.0.7 → qis-3.0.8}/qis/examples/boxplot_conditional_returns.py +0 -0
  13. {qis-3.0.7 → qis-3.0.8}/qis/examples/btc_asset_corr.py +0 -0
  14. {qis-3.0.7 → qis-3.0.8}/qis/examples/constant_notional.py +0 -0
  15. {qis-3.0.7 → qis-3.0.8}/qis/examples/constant_weight_portfolios.py +0 -0
  16. {qis-3.0.7 → qis-3.0.8}/qis/examples/core/perf_bbg_prices.py +0 -0
  17. {qis-3.0.7 → qis-3.0.8}/qis/examples/core/price_plots.py +0 -0
  18. {qis-3.0.7 → qis-3.0.8}/qis/examples/core/us_election.py +0 -0
  19. {qis-3.0.7 → qis-3.0.8}/qis/examples/credit_spreads.py +0 -0
  20. {qis-3.0.7 → qis-3.0.8}/qis/examples/credit_trackers.py +0 -0
  21. {qis-3.0.7 → qis-3.0.8}/qis/examples/europe_futures.py +0 -0
  22. {qis-3.0.7 → qis-3.0.8}/qis/examples/factsheets/multi_assets.py +0 -0
  23. {qis-3.0.7 → qis-3.0.8}/qis/examples/factsheets/multi_strategy.py +0 -0
  24. {qis-3.0.7 → qis-3.0.8}/qis/examples/factsheets/pyblogs_reports.py +0 -0
  25. {qis-3.0.7 → qis-3.0.8}/qis/examples/factsheets/strategy.py +0 -0
  26. {qis-3.0.7 → qis-3.0.8}/qis/examples/factsheets/strategy_benchmark.py +0 -0
  27. {qis-3.0.7 → qis-3.0.8}/qis/examples/generate_option_rolls.py +0 -0
  28. {qis-3.0.7 → qis-3.0.8}/qis/examples/interpolation_infrequent_returns.py +0 -0
  29. {qis-3.0.7 → qis-3.0.8}/qis/examples/leveraged_strategies.py +0 -0
  30. {qis-3.0.7 → qis-3.0.8}/qis/examples/long_short.py +0 -0
  31. {qis-3.0.7 → qis-3.0.8}/qis/examples/momentum_indices.py +0 -0
  32. {qis-3.0.7 → qis-3.0.8}/qis/examples/oakmark_analysis.py +0 -0
  33. {qis-3.0.7 → qis-3.0.8}/qis/examples/ohlc_vol_analysis.py +0 -0
  34. {qis-3.0.7 → qis-3.0.8}/qis/examples/overnight_returns.py +0 -0
  35. {qis-3.0.7 → qis-3.0.8}/qis/examples/perf_external_assets.py +0 -0
  36. {qis-3.0.7 → qis-3.0.8}/qis/examples/perp_pricing.py +0 -0
  37. {qis-3.0.7 → qis-3.0.8}/qis/examples/readme_performances.py +0 -0
  38. {qis-3.0.7 → qis-3.0.8}/qis/examples/risk_return_frontier.py +0 -0
  39. {qis-3.0.7 → qis-3.0.8}/qis/examples/rolling_performance.py +0 -0
  40. {qis-3.0.7 → qis-3.0.8}/qis/examples/seasonality.py +0 -0
  41. {qis-3.0.7 → qis-3.0.8}/qis/examples/sharpe_vs_sortino.py +0 -0
  42. {qis-3.0.7 → qis-3.0.8}/qis/examples/simulate_quant_strats.py +0 -0
  43. {qis-3.0.7 → qis-3.0.8}/qis/examples/test_ewm.py +0 -0
  44. {qis-3.0.7 → qis-3.0.8}/qis/examples/test_scatter.py +0 -0
  45. {qis-3.0.7 → qis-3.0.8}/qis/examples/try_pybloqs.py +0 -0
  46. {qis-3.0.7 → qis-3.0.8}/qis/examples/universe_corrs.py +0 -0
  47. {qis-3.0.7 → qis-3.0.8}/qis/examples/vix_beta_to_equities_bonds.py +0 -0
  48. {qis-3.0.7 → qis-3.0.8}/qis/examples/vix_conditional_returns.py +0 -0
  49. {qis-3.0.7 → qis-3.0.8}/qis/examples/vix_spy_by_year.py +0 -0
  50. {qis-3.0.7 → qis-3.0.8}/qis/examples/vix_tenor_analysis.py +0 -0
  51. {qis-3.0.7 → qis-3.0.8}/qis/examples/vol_without_weekends.py +0 -0
  52. {qis-3.0.7 → qis-3.0.8}/qis/file_utils.py +0 -0
  53. {qis-3.0.7 → qis-3.0.8}/qis/local_path.py +0 -0
  54. {qis-3.0.7 → qis-3.0.8}/qis/models/README.md +0 -0
  55. {qis-3.0.7 → qis-3.0.8}/qis/models/__init__.py +0 -0
  56. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/__init__.py +0 -0
  57. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/auto_corr.py +0 -0
  58. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/corr_cov_matrix.py +0 -0
  59. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/ewm.py +0 -0
  60. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/ewm_convolution.py +0 -0
  61. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/ewm_factors.py +0 -0
  62. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/ewm_winsor_outliers.py +0 -0
  63. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/pca.py +0 -0
  64. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/plot_correlations.py +0 -0
  65. {qis-3.0.7 → qis-3.0.8}/qis/models/linear/ra_returns.py +0 -0
  66. {qis-3.0.7 → qis-3.0.8}/qis/models/stats/__init__.py +0 -0
  67. {qis-3.0.7 → qis-3.0.8}/qis/models/stats/bootstrap.py +0 -0
  68. {qis-3.0.7 → qis-3.0.8}/qis/models/stats/ohlc_vol.py +0 -0
  69. {qis-3.0.7 → qis-3.0.8}/qis/models/stats/rolling_stats.py +0 -0
  70. {qis-3.0.7 → qis-3.0.8}/qis/models/stats/test_bootstrap.py +0 -0
  71. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/README.md +0 -0
  72. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/__init__.py +0 -0
  73. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/cond_regression.py +0 -0
  74. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/config.py +0 -0
  75. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/desc_table.py +0 -0
  76. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/fx_ops.py +0 -0
  77. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/perf_stats.py +0 -0
  78. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/regime_classifier.py +0 -0
  79. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/returns.py +0 -0
  80. {qis-3.0.7 → qis-3.0.8}/qis/perfstats/timeseries_bfill.py +0 -0
  81. {qis-3.0.7 → qis-3.0.8}/qis/plots/README.md +0 -0
  82. {qis-3.0.7 → qis-3.0.8}/qis/plots/__init__.py +0 -0
  83. {qis-3.0.7 → qis-3.0.8}/qis/plots/bars.py +0 -0
  84. {qis-3.0.7 → qis-3.0.8}/qis/plots/boxplot.py +0 -0
  85. {qis-3.0.7 → qis-3.0.8}/qis/plots/contour.py +0 -0
  86. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/__init__.py +0 -0
  87. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/data_timeseries.py +0 -0
  88. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/desc_table.py +0 -0
  89. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/drawdowns.py +0 -0
  90. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/perf_table.py +0 -0
  91. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/prices.py +0 -0
  92. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/regime_class_table.py +0 -0
  93. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/regime_data.py +0 -0
  94. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/regime_pdf.py +0 -0
  95. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/regime_scatter.py +0 -0
  96. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/returns_heatmap.py +0 -0
  97. {qis-3.0.7 → qis-3.0.8}/qis/plots/derived/returns_scatter.py +0 -0
  98. {qis-3.0.7 → qis-3.0.8}/qis/plots/errorbar.py +0 -0
  99. {qis-3.0.7 → qis-3.0.8}/qis/plots/heatmap.py +0 -0
  100. {qis-3.0.7 → qis-3.0.8}/qis/plots/histogram.py +0 -0
  101. {qis-3.0.7 → qis-3.0.8}/qis/plots/histplot2d.py +0 -0
  102. {qis-3.0.7 → qis-3.0.8}/qis/plots/lineplot.py +0 -0
  103. {qis-3.0.7 → qis-3.0.8}/qis/plots/pie.py +0 -0
  104. {qis-3.0.7 → qis-3.0.8}/qis/plots/qqplot.py +0 -0
  105. {qis-3.0.7 → qis-3.0.8}/qis/plots/reports/__init__.py +0 -0
  106. {qis-3.0.7 → qis-3.0.8}/qis/plots/reports/econ_data_single.py +0 -0
  107. {qis-3.0.7 → qis-3.0.8}/qis/plots/reports/gantt_data_history.py +0 -0
  108. {qis-3.0.7 → qis-3.0.8}/qis/plots/reports/price_history.py +0 -0
  109. {qis-3.0.7 → qis-3.0.8}/qis/plots/reports/utils.py +0 -0
  110. {qis-3.0.7 → qis-3.0.8}/qis/plots/scatter.py +0 -0
  111. {qis-3.0.7 → qis-3.0.8}/qis/plots/stackplot.py +0 -0
  112. {qis-3.0.7 → qis-3.0.8}/qis/plots/table.py +0 -0
  113. {qis-3.0.7 → qis-3.0.8}/qis/plots/utils.py +0 -0
  114. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/README.md +0 -0
  115. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/__init__.py +0 -0
  116. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/backtester.py +0 -0
  117. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/ewm_portfolio_risk.py +0 -0
  118. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/multi_portfolio_data.py +0 -0
  119. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/portfolio_data.py +0 -0
  120. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/__init__.py +0 -0
  121. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/config.py +0 -0
  122. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/multi_assets_factsheet.py +0 -0
  123. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/multi_strategy_factseet_pybloqs.py +0 -0
  124. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/multi_strategy_factsheet.py +0 -0
  125. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/strategy_benchmark_factsheet_pybloqs.py +0 -0
  126. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/strategy_factsheet.py +0 -0
  127. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/reports/strategy_signal_factsheet.py +0 -0
  128. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/strats/__init__.py +0 -0
  129. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/strats/quant_strats_delta1.py +0 -0
  130. {qis-3.0.7 → qis-3.0.8}/qis/portfolio/strats/seasonal_strats.py +0 -0
  131. {qis-3.0.7 → qis-3.0.8}/qis/settings.yaml +0 -0
  132. {qis-3.0.7 → qis-3.0.8}/qis/sql_engine.py +0 -0
  133. {qis-3.0.7 → qis-3.0.8}/qis/test_data.py +0 -0
  134. {qis-3.0.7 → qis-3.0.8}/qis/utils/README.md +0 -0
  135. {qis-3.0.7 → qis-3.0.8}/qis/utils/__init__.py +0 -0
  136. {qis-3.0.7 → qis-3.0.8}/qis/utils/dates.py +0 -0
  137. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_agg.py +0 -0
  138. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_cut.py +0 -0
  139. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_freq.py +0 -0
  140. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_groups.py +0 -0
  141. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_melt.py +0 -0
  142. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_ops.py +0 -0
  143. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_str.py +0 -0
  144. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_to_scores.py +0 -0
  145. {qis-3.0.7 → qis-3.0.8}/qis/utils/df_to_weights.py +0 -0
  146. {qis-3.0.7 → qis-3.0.8}/qis/utils/generic.py +0 -0
  147. {qis-3.0.7 → qis-3.0.8}/qis/utils/np_ops.py +0 -0
  148. {qis-3.0.7 → qis-3.0.8}/qis/utils/ols.py +0 -0
  149. {qis-3.0.7 → qis-3.0.8}/qis/utils/sampling.py +0 -0
  150. {qis-3.0.7 → qis-3.0.8}/qis/utils/struct_ops.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: qis
3
- Version: 3.0.7
3
+ Version: 3.0.8
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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "qis"
3
- version = "3.0.7"
3
+ version = "3.0.8"
4
4
  description = "Implementation of visualisation and reporting analytics for Quantitative Investment Strategies"
5
5
  license = "LICENSE.txt"
6
6
  authors = ["Artur Sepp <artursepp@gmail.com>"]
@@ -124,25 +124,26 @@ def plot_time_series(df: Union[pd.Series, pd.DataFrame],
124
124
  elif trend_line in [TrendLine.TREND_LINE, TrendLine.TREND_LINE_SHADOWS]:
125
125
  for column, color in zip(columns, trend_line_colors):
126
126
  y = data1[column].dropna()
127
- x0 = y.first_valid_index() or y.index[0] # if all are nons
128
- x1 = y.index[-1]
129
- y0 = y[x0]
130
- y1 = y.iloc[-1]
131
- x = [x0, x1]
132
- y = [y0, y1]
133
- ax.plot(x, y,
134
- color=color,
135
- linestyle='--',
136
- transform=ax.transData,
137
- linewidth=linewidth)
138
-
139
- if trend_line == TrendLine.TREND_LINE_SHADOWS:
140
- x_ = (data1.index - data1.index[0]).days
141
- slope = (y1 - y0) / (x_[-1] - x_[0])
142
- y_line = [slope * x + y0 for x in x_]
143
- y = data1[column]
144
- ax.fill_between(data1.index, y, y_line, where=y_line >= y,
145
- facecolor=color, interpolate=True, alpha=0.2, lw=linewidth)
127
+ if not y.empty:
128
+ x0 = y.first_valid_index()
129
+ x1 = y.index[-1]
130
+ y0 = y[x0]
131
+ y1 = y.iloc[-1]
132
+ x = [x0, x1]
133
+ y = [y0, y1]
134
+ ax.plot(x, y,
135
+ color=color,
136
+ linestyle='--',
137
+ transform=ax.transData,
138
+ linewidth=linewidth)
139
+
140
+ if trend_line == TrendLine.TREND_LINE_SHADOWS:
141
+ x_ = (data1.index - data1.index[0]).days
142
+ slope = (y1 - y0) / (x_[-1] - x_[0])
143
+ y_line = [slope * x + y0 for x in x_]
144
+ y = data1[column]
145
+ ax.fill_between(data1.index, y, y_line, where=y_line >= y,
146
+ facecolor=color, interpolate=True, alpha=0.2, lw=linewidth)
146
147
 
147
148
  # add last labels
148
149
  if last_label in [LastLabel.AVERAGE_VALUE, LastLabel.AVERAGE_VALUE_SORTED]:
@@ -174,7 +174,7 @@ def plot_brinson_totals_table(totals_table: pd.DataFrame,
174
174
  **kwargs
175
175
  ) -> Optional[plt.Figure]:
176
176
  special_rows_colors = [(len(totals_table.index), 'steelblue')]
177
- rows_edge_lines = [len(totals_table.columns)] # line before totals
177
+ rows_edge_lines = [len(totals_table.index)-1] # line before totals
178
178
 
179
179
  special_columns_colors = [(0, 'lightblue'),
180
180
  (len(totals_table.columns), 'steelblue')]
@@ -652,6 +652,7 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
652
652
  multi_portfolio_data.plot_tre_time_series(strategy_idx=strategy_idx,
653
653
  benchmark_idx=benchmark_idx,
654
654
  regime_benchmark=regime_benchmark,
655
+ regime_params=regime_params,
655
656
  ax=ax,
656
657
  time_period=time_period,
657
658
  **kwargs)
@@ -673,15 +674,17 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
673
674
  figs['brinson_total_time_series'] = fig
674
675
  qis.plot_time_series(df=active_total.cumsum(axis=0),
675
676
  title='Active total return',
677
+ var_format='{:.0%}',
676
678
  ax=ax, **kwargs)
677
679
  if regime_benchmark is not None:
678
680
  multi_portfolio_data.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark,
679
- index=grouped_allocation_return.index, regime_params=regime_params)
681
+ index=active_total.index, regime_params=regime_params)
680
682
 
681
683
  fig, ax = plt.subplots(1, 1, figsize=figsize, tight_layout=True)
682
684
  figs['brinson_grouped_allocation_return'] = fig
683
685
  qis.plot_time_series(df=grouped_allocation_return.cumsum(axis=0),
684
686
  title='Grouped allocation return',
687
+ var_format='{:.0%}',
685
688
  ax=ax, **kwargs)
686
689
  if regime_benchmark is not None:
687
690
  multi_portfolio_data.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark,
@@ -691,10 +694,11 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
691
694
  figs['brinson_grouped_selection_return'] = fig
692
695
  qis.plot_time_series(df=grouped_selection_return.cumsum(axis=0),
693
696
  title='Grouped selection return',
697
+ var_format='{:.0%}',
694
698
  ax=ax, **kwargs)
695
699
  if regime_benchmark is not None:
696
700
  multi_portfolio_data.add_regime_shadows(ax=ax, regime_benchmark=regime_benchmark,
697
- index=grouped_allocation_return.index, regime_params=regime_params)
701
+ index=grouped_selection_return.index, regime_params=regime_params)
698
702
 
699
703
  # brinson by sub-asset class
700
704
  totals_table, active_total, grouped_allocation_return, grouped_selection_return, grouped_interaction_return = \
@@ -715,6 +719,7 @@ def weights_tracking_error_report_by_ac_subac(multi_portfolio_data: MultiPortfol
715
719
  multi_portfolio_data.plot_turnover(ax=ax,
716
720
  time_period=time_period,
717
721
  regime_benchmark=regime_benchmark,
722
+ regime_params=regime_params,
718
723
  #turnover_rolling_period=260,
719
724
  #freq_turnover=None,
720
725
  **kwargs)
@@ -744,7 +749,7 @@ def plot_exposures_long_short_groups(exposures_short: pd.DataFrame,
744
749
  y_var_name=ylabel,
745
750
  ylabel=ylabel,
746
751
  showmedians=True,
747
- add_y_median_labels=True,
752
+ add_y_median_labels=False,
748
753
  yvar_format=var_format,
749
754
  x_rotation=90,
750
755
  colors=qis.get_n_sns_colors(n=len(exposures_long.columns)),
@@ -803,7 +808,7 @@ def plot_exposures_strategy_vs_benchmark_boxplot(strategy_exposures: pd.DataFram
803
808
  y_var_name=ylabel,
804
809
  ylabel=ylabel,
805
810
  showmedians=True,
806
- add_y_median_labels=True,
811
+ add_y_median_labels=False,
807
812
  yvar_format=var_format,
808
813
  x_rotation=90,
809
814
  title=title,
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