import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
ファイルの読み込み
file_path = 'path_to_your_local_file/合成用資料_1.xlsx' # ローカルファイルのパスに置き換えてください
data = pd.read_excel(file_path)
日付をdatetime型に変換
data['TDATE'] = pd.to_datetime(data['TDATE'], format='%Y%m%d')
1年ごとの期間設定
years = data['TDATE'].dt.year.unique()
ファクターポートフォリオの構築と評価
factor_names = ['EST_SENTIMENT', 'EST_LIQUIDITY', 'INCM_NORM']
results = {year: {factor: [] for factor in factor_names} for year in years}
for year in years:
year_data = data[data['TDATE'].dt.year == year]
for factor in factor_names:
factor_portfolio = year_data.sort_values(by=factor, ascending=False).iloc[:int(len(year_data) * 0.1)]
cumulative_return = (factor_portfolio['ROR1MF'] / 100 + 1).prod() - 1
average_return = factor_portfolio['ROR1MF'].mean()
risk = factor_portfolio['ROR1MF'].std()
sharpe_ratio = average_return / risk if risk != 0 else np.nan
results[year][factor] = {
'Cumulative Return': cumulative_return,
'Average Return': average_return,
'Risk': risk,
'Sharpe Ratio': sharpe_ratio
}
ウェイトの計算
weights = {}
for year in years:
weights[year] = {}
total_sharpe = sum(results[year][factor]['Sharpe Ratio'] for factor in factor_names if results[year][factor]['Sharpe Ratio'] > 0)
for factor in factor_names:
sharpe_ratio = results[year][factor]['Sharpe Ratio']
weights[year][factor] = sharpe_ratio / total_sharpe if total_sharpe > 0 else 1 / len(factor_names)
ウェイトを適用した戦略合成の計算
strategy_results = []
for year in years:
year_data = data[data['TDATE'].dt.year == year]
year_strategy_return = np.zeros(len(year_data))
for factor in factor_names:
weight = weights[year][factor]
normalized_factor = (year_data[factor] - year_data[factor].mean()) / year_data[factor].std()
year_strategy_return += weight * normalized_factor
strategy_results.append({
'Year': year,
'Strategy Return': year_strategy_return.mean()
})
結果のデータフレーム化
strategy_results_df = pd.DataFrame(strategy_results)
プロットの準備
years = strategy_results_df['Year']
strategy_returns = strategy_results_df['Strategy Return']
比較のための正規化した単純合成
simple_composite = (data['EST_SENTIMENT'] + data['EST_LIQUIDITY'] + data['INCM_NORM']) / 3
simple_composite_return = []
for year in years:
year_data = data[data['TDATE'].dt.year == year]
simple_composite_return.append(simple_composite[year_data.index].mean())
プロット
plt.figure(figsize=(12, 8))
plt.plot(years, simple_composite_return, label='Simple Composite', marker='o')
plt.plot(years, strategy_returns, label='Strategy Composite', marker='x')
plt.xlabel('Year')
plt.ylabel('Average Return')
plt.title('Simple Composite vs Strategy Composite Returns')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()