メインコンテンツへスキップ

量子ポートフォリオオプティマイザー: Global Data QuantumによるQiskit Function

備考

Qiskit Functionsは、IBM Quantum® Premiumプラン、Flexプラン、およびOn-Prem(IBM Quantum Platform API経由)プランのユーザーのみが利用できる実験的な機能です。プレビューリリースの状態であり、変更される場合があります。

概要

量子ポートフォリオオプティマイザーは、動的ポートフォリオ最適化問題に取り組むQiskit Functionです。これは、リターンを最大化しリスクを最小化するために、一連の資産にわたる定期的な投資のリバランスを目的とする、金融における標準的な問題です。最先端の量子最適化技術を活用することで、この関数はプロセスを簡素化し、量子コンピューティングの専門知識がないユーザーでも、最適な投資トラジェクトリーを見つけるうえでその利点を活用できるようにします。ポートフォリオマネージャー、定量的金融の研究者、および個人投資家に最適で、このツールはポートフォリオ最適化における取引戦略のバックテストを可能にします。

関数の説明

量子ポートフォリオオプティマイザー関数は、変分量子固有値ソルバー(VQE)アルゴリズムを使用して二次制約なし二値最適化(QUBO)問題を解き、動的ポートフォリオ最適化問題に対処します。ユーザーは資産価格データを提供し、投資制約を定義するだけで、関数が量子最適化プロセスを実行し、最適化された投資トラジェクトリーのセットを返します。

このプロセスは4つの主要なステージで構成されています。まず、入力データを量子互換の問題にマッピングし、動的ポートフォリオ最適化問題のQUBOを構築し、量子演算子(イジングハミルトニアン)に変換します。次に、入力問題とVQEアルゴリズムを量子ハードウェア上で実行できるように適応させます。その後、VQEアルゴリズムを量子ハードウェア上で実行し、最後に結果をポストプロセッシングして最適な投資トラジェクトリーを提供します。このシステムにはノイズ対応(SQDベース)のポストプロセッシングも含まれており、出力の品質を最大化します。

このQiskit FunctionはGlobal Data Quantumによる公開論文に基づいています。 関数のワークフローの可視化

入力

関数の入力引数を以下の表に説明します。資産データとその他の問題仕様は必須です。また、最適化プロセスをカスタマイズするためにVQEの設定を含めることもできます。

名前説明必須デフォルト
assetsjson資産価格を含む辞書はい--
qubo_settingsjsonQUBOの設定はい-以下の表の例を参照
ansatz_settingsjsonアンザッツの設定いいえNone以下の表の例を参照
optimizer_settingsjsonオプティマイザーの設定いいえNone以下の表の例を参照
backendstrQPUバックエンド名いいえ-"ibm_torino"
previous_session_idstrのリスト以前の実行からデータを取得するためのセッションIDのリスト(*)いいえ空リスト["session_id_1", "session_id_2"]
apply_postprocessboolノイズ対応SQDポストプロセッシングを適用するいいえTrueTrue
tags文字列のリスト実験を識別するためのタグのリストいいえ空リスト["optimization", "quantum_computing"]

*実行を再開する場合や、1つ以上の以前のセッションで処理されたジョブを取得する場合は、セッションIDのリストをprevious_session_idパラメーターに渡す必要があります。これは、プロセスのエラーにより最適化タスクが完了しなかった場合や、実行を完了させる必要がある場合に特に便利です。これを実現するには、最初の実行で使用したものと同じ引数を提供し、説明に従ってprevious_session_idリストを追加してください。

警告

以前のセッションのデータの読み込み(最適化を再開するため)には最大1時間かかる場合があります。

assets

データは、特定の日付における金融資産の終値に関する情報を格納するJSONオブジェクトとして構造化する必要があります。形式は以下の通りです:

  • プライマリキー(文字列):金融資産の名前またはティッカーシンボル(例:「8801.T」)。
  • セカンダリキー(文字列):YYYY-MM-DD形式の日付。
  • 値(数値):指定された日付における資産の終値。価格は正規化されていてもされていなくても入力できます。

すべての辞書が同じセカンダリキー(日付)を持つ必要があることに注意してください。特定の資産に他の資産が持つ日付がない場合は、一貫性を確保するためにデータを補完する必要があります。例えば、その資産の直近の終値を使用することで対応できます。

{
"8801.T": {
"2023-01-01": 2374.0,
"2023-01-02": 2374.0,
"2023-01-03": 2374.0,
"2023-01-04": 2356.5,
...
},
"AAPL": {
"2023-01-01": 145.2,
"2023-01-02": 146.5,
"2023-01-03": 147.3,
"2023-01-04": 148.1,
...
},
...
}
# Added by doQumentation — required packages for this notebook
!pip install -q pandas qiskit-ibm-catalog
{
"asset_name": {
"date": closing_value,
...
},
...
}
備考

資産データには、少なくとも(nt+1) * dtqubo_settings入力セクションを参照)タイムスタンプ(例:日数)の終値が含まれている必要があります。

qubo_settings

次の表はqubo_settings辞書のキーを説明しています。タイムステップ数nt、分解量子ビット数nq、およびmax_investmentを指定して辞書を構築するか、その他のデフォルト値を変更してください。

名前説明必須デフォルト
ntintタイムステップ数はい-4
nqint分解量子ビット数はい-4
max_investmentfloatすべての資産にわたる投資通貨単位の最大数はい-10
dt*int各タイムステップで考慮される時間ウィンドウ。単位は資産データのキー間の時間間隔と一致しますいいえ30-
risk_aversionfloatリスク回避係数いいえ1000-
transaction_feefloat取引手数料係数いいえ0.01-
restriction_coefffloatQUBO定式化内で問題の制約を強制するために使用されるラグランジュ乗数いいえ1-

ansatz_settings

デフォルトオプションを変更するには、以下のキーを持つansatz_settingsパラメーターの辞書を作成してください。デフォルトでは、アンザッツは"real_amplitudes"に設定されており、両方の追加オプション(以下の表を参照)はFalseに設定されています。

名前説明必須デフォルト
ansatz*str使用するアンザッツいいえ"real_amplitudes"
multiple_passmanager**bool複数のパスマネージャーサブルーチンを有効にします(Tailoredアンザッツでは利用不可)いいえFalse
dd_enableboolダイナミカルデカップリングを追加しますいいえFalse

* 利用可能なアンザッツ

  • real_amplitudes
  • cyclic
  • optimized_real_amplitudes
  • tailoredibm_torinoバックエンド、7資産、4タイムステップ、4分解量子ビットのみ)

** multiple_passmanagerFalseに設定されている場合、関数はデフォルトのQiskitパスマネージャー(optimization_level=3)を使用します。Trueに設定されている場合、multiple_passmanagerサブルーチンは3つのパスマネージャーを比較します:前述のデフォルトQiskitパスマネージャー、QPUの最近傍チェーン上に量子ビットをマッピングするパスマネージャー、およびAIトランスパイラーサービス。その後、推定される累積エラーが最も低いパスマネージャーが選択されます。

optimizer_settings

このパラメーターは、最適化プロセスの調整可能なオプションを持つ辞書です。

名前説明必須デフォルト
primitive_optionsjsonプリミティブの設定いいえ-
optimizerstr選択されたクラシカルオプティマイザーいいえ"differential_evolution"
optimizer_optionsjsonオプティマイザーの設定いいえ-
備考

現在、利用可能なオプティマイザーオプションは"differential_evolution"のみです。

primitive_optionsおよびoptimizer_optionsキーの下に、以下のパラメーターを持つ辞書を設定します:

primitive_options

名前説明必須デフォルト
sampler_shotsintSamplerのショット数いいえ100000-
estimator_shotsintEstimatorのショット数いいえ25000-
estimator_precisionfloat期待値の所望精度。指定した場合、estimator_shotsの代わりに精度が使用されます。いいえNone0.015625 · (1 / sqrt(4096))
max_timeint または strランタイムセッションが強制終了される前に開いたままにできる最大時間。秒(int)または"2h 30m 40s"のような文字列で指定できます。システムが定める最大値未満である必要があります。いいえNone"1h 15m"

optimizer_options

名前説明必須デフォルト
num_generationsint世代数いいえ20
population_sizeint集団サイズいいえ20
mutation_rangelist最大および最小変異係数いいえ[0, 0.25]
recombinationfloat組換え係数いいえ0.4
max_parallel_jobsint並列実行されるQPUジョブの最大数いいえ3
max_batchsizeint最大バッチサイズいいえ200
備考
  • 差分進化によって評価される世代数は、初期集団が含まれるためnum_generations + 1となります。

  • 回路の総数は(num_generations + 1) * population_sizeとして計算されます。

  • 一般的に、集団サイズを大きくし世代数を増やすと、最適化結果の品質が向上します。ただし、集団サイズを120を超えて設定し、世代数を20より大きくすること(例:120 * 21 = 2520回路の合計)は推奨されません。これにより回路数が過多となり、計算コストと処理時間が大幅に増加します。

  • この関数は以前の最適化を再開することができ、世代数を増やすことは常に可能です(previous_session_id以外は同じ入力を提供し、num_generationsを増加させることで対応できます)。

備考

Qiskit Runtimeのジョブ制限に準拠していることを確認してください。

  • Sampler:sampler_shots <= 10_000_000
  • Estimator:max_batchsize * estimator_shots * observable_size <= 10_000_000(この関数では、オブザーバブルのすべての項が可換であるためobservable_size=1)。

詳細はジョブ制限ガイドを参照してください。

出力

関数は2つの辞書を返します:最適な解とその関連する最小目的コストを含む最良の最適化結果を格納する"result"辞書と、最適化プロセス中に得られたすべての結果のデータとその各メトリクスを含む"metadata"です。

最初の辞書は最良のパフォーマンスを示す解に焦点を当て、2番目の辞書は目的コストやその他の関連メトリクスを含む、すべての解に関する詳細情報を提供します。

出力辞書:

名前説明
resultdict[str, dict[str, float]]時系列の投資戦略を格納しており、各タイムスタンプが資産固有の投資ウェイト(各ウェイトは総投資額で正規化された投資額)にマッピングされています。{'time_1': {'asset_1': 0.2, 'asset_2': 0.3, ...\}, ...\}
metadatadict[str, Any]解、コスト、メトリクスを含む分析中に生成されたデータ。以下の例を参照

metadata辞書の説明

名前説明
session_idstrIBM Quantumセッションの一意の識別子。"d0h30qjvpqf00084fgw0"
all_samples_metricsdictコストや制約など、各ポストプロセッシングされたサンプルの各種メトリクスを含む辞書。以下の説明を参照
sampler_countsdict[str, int]キーがサンプリングされた解のビット文字列表現で、値がそのカウントである辞書。{"101010": 3, "111000": 1\}
asset_orderlist[str]投資戦略内の各タイムステップにおける資産の投資順序を示すリスト。["Asset_0", "Asset_1", "Asset_3"]
QUBOlist[list[float]]問題のQUBO行列。[[-6.96e-01, 5.81e-01, -1.26e-02, 0.00e+00], ...]
resource_summarydict[str, dict[str, float]]プロセスの各ステージにわたるCPUおよびQPUの使用時間(秒)の概要。{'RUNNING: EXECUTING_QPU': {'CPU_TIME': 412.84, 'QPU_TIME': 87.22\}, ...\}

all_samples_metrics辞書の説明

名前説明
investment_trajectorieslist[list]デコードされた量子状態から導出された投資戦略。[[1, 2, 2], [1, 2, 1]]

| counts | list[int] | 各投資トラジェクトリーがサンプリングされた回数。インデックスはinvestment_trajectoriesと対応します。 | [5, 3] | | objective_costs | list[float] | 各投資トラジェクトリーの目的関数値。最小から最大の順に並べられています。 | [0.98, 1.25] | | sharpe_ratios | list[float] | 各投資トラジェクトリーのリスク調整後パフォーマンス(シャープ比)。インデックス順に整列されています。 | [1.1, 0.7] | | returns | list[float] | 各投資トラジェクトリーの期待リターン。インデックス順に整列されています。 | [0.15, 0.10] | | rest_breaches | list[float] | 各投資トラジェクトリー内の最大制約逸脱量。インデックス順に整列されています。 | [0.0, 0.25] | | transaction_costs | list[float] | 各投資トラジェクトリーに関連する推定取引コスト。インデックス順に整列されています。 | [0.01, 0.02] |

はじめに

APIキーを使用して認証し、以下のようにQiskit Functionを選択してください。(このコードスニペットは、アカウントをローカル環境に保存済みであることを前提としています。)

from qiskit_ibm_catalog import QiskitFunctionsCatalog

catalog = QiskitFunctionsCatalog(channel="ibm_quantum_platform")

# Access function
dpo_solver = catalog.load("global-data-quantum/quantum-portfolio-optimizer")

例:7資産を用いた動的ポートフォリオ最適化

この例では、動的ポートフォリオ最適化(DPO)関数を実行し、最適なパフォーマンスを得るためにその設定を調整する方法を示します。最適な結果を得るためにパラメーターをファインチューニングするための詳細な手順が含まれています。

このケースでは、7資産、4タイムステップ、4分解量子ビットを使用しており、合計112量子ビットが必要となります。

1. ポートフォリオに含まれる資産を読み込む。

ポートフォリオのすべての資産が特定のパスのフォルダーに保存されている場合、以下の関数を使用してpandas.DataFrameに読み込み、dict形式のオブジェクトに変換できます。

import os
import glob
import pandas as pd

def read_and_join_csv(file_pattern):
"""
Reads multiple CSV files matching the file pattern and combines them into a single DataFrame.

Parameters:
file_pattern (str): The pattern to match CSV files.

Returns:
pd.DataFrame: Combined DataFrame with data from all CSV files.
"""
# Find all files matching the pattern
csv_files = glob.glob(file_pattern)
# Get the base file names without the .csv extension
file_names = [os.path.basename(f).replace(".csv", "") for f in csv_files]
# Read each CSV file into a DataFrame and set the first column as the index
df_list = [pd.read_csv(f).set_index("Unnamed: 0") for f in csv_files]

# Rename columns in each DataFrame to the base file names
for df, name in zip(df_list, file_names):
df.columns = [name]

# Combine all DataFrames into one by merging them side by side
combined_df = pd.concat(df_list, axis=1)
return combined_df

file_pattern = "route/to/folder/with/assets/data/*.csv"
assets = read_and_join_csv(file_pattern).to_dict()

この例では、8801.TCLFGBPJPYITX.MCMETATMBMKDE-10Y、およびXS2239553048の資産を使用しています。以下の図は、この例で使用したデータを示しており、2023年1月1日から9月1日までの資産の日次終値の推移を示しています。

この例では、日付全体で均一性を確保するために、非取引日には直前の利用可能な日付の終値を補完しています。選択した資産が取引日の異なる複数の市場に属しているため、データセットの一貫性を標準化するためにこのステップを適用しています。 資産の過去データの可視化

2. 問題を定義する。

qubo_settings辞書でパラメーターを設定して、問題の仕様を定義してください。

qubo_settings = {
"nt": 4,
"nq": 4,
"dt": 30,
"max_investment": 25,
"risk_aversion": 1000.0,
"transaction_fee": 0.01,
"restriction_coeff": 1.0,
}

3. オプティマイザーとアンザッツの設定を定義する。(オプション)

オプションで、オプティマイザーとそのパラメーターの選択、およびプリミティブとその設定の指定を含む、最適化プロセスに関する特定の要件を定義します。

Tailored Ansatzの場合、選択された集団サイズは、この値が安定した効率的な最適化をもたらすことを示す以前の実験に基づいています。

Real Amplitudes Ansatzの場合、population_sizeと回路内の量子ビット数の間の線形関係に従うことができます。経験則として、real_amplitudesアンザッツには最低population_size ~ 0.8 * n_qubitsを使用することが推奨されます。

Optimized Real AmplitudesはReal Amplitudesアンザッツよりも優れた最適化性能を発揮することが期待されます。ただし、このアンザッツで最適化する変数の数はReal Amplitudesの場合よりもはるかに速く増加します(論文を参照)。したがって、大規模な問題では、Optimized Real Amplitudesはより多くの回路実行が必要です。Optimized Real Amplitudesは最大100量子ビットを必要とする問題に有効である可能性が高いですが、population_sizeパラメーターを設定する際には注意が必要です。このpopulation_sizeのスケールアップの例として、前の表では84量子ビットの問題でOptimize Real Amplitudesが120のpopulation_sizeを必要とするのに対し、56量子ビットの問題では40のpopulation_sizeで十分であることを示しています。

optimizer_settings = {
"de_optimizer_settings": {
"num_generations": 20,
"population_size": 90,
"recombination": 0.4,
"max_parallel_jobs": 5,
"max_batchsize": 4,
"mutation_range": [0.0, 0.25],
},
"optimizer": "differential_evolution",
"primitive_settings": {
"estimator_shots": 25_000,
"estimator_precision": None,
"sampler_shots": 100_000,
},
}

特定のアンザッツを選択することもできます。以下では'Tailored'アンザッツを使用します。

ansatz_settings = {
"ansatz": "tailored",
"multiple_passmanager": False,
}

4. 問題を実行する。

dpo_job = dpo_solver.run(
assets=assets,
qubo_settings=qubo_settings,
optimizer_settings=optimizer_settings,
ansatz_settings=ansatz_settings,
backend_name="<backend name>",
previous_session_id=[],
apply_postprocess=True,
)

5. 結果を取得する。

出力セクションで述べたように、関数は目的関数値に基づいて最小から最大の順に並べられた投資トラジェクトリーを含む辞書を返します。この結果セットにより、最低コストのトラジェクトリーとその対応する投資評価を特定できます。また、さまざまなトラジェクトリーの分析が可能で、特定のニーズや目標に最も合致するものを選択しやすくなります。この柔軟性により、さまざまな好みやシナリオに合わせた選択が可能です。 まず、プロセス中に見つかった最低の目的コストを達成した結果戦略を提示します。

# Get the results of the job
dpo_result = dpo_job.result()

# Show the solution strategy
dpo_result["result"]
{'time_step_0': {'8801.T': 0.11764705882352941,
'ITX.MC': 0.20588235294117646,
'META': 0.38235294117647056,
'GBPJPY=X': 0.058823529411764705,
'TMBMKDE-10Y': 0.0,
'CLF': 0.058823529411764705,
'XS2239553048': 0.17647058823529413},
'time_step_1': {'8801.T': 0.11428571428571428,
'ITX.MC': 0.14285714285714285,
'META': 0.2,
'GBPJPY=X': 0.02857142857142857,
'TMBMKDE-10Y': 0.42857142857142855,
'CLF': 0.0,
'XS2239553048': 0.08571428571428572},
'time_step_2': {'8801.T': 0.0,
'ITX.MC': 0.09375,
'META': 0.3125,
'GBPJPY=X': 0.34375,
'TMBMKDE-10Y': 0.0,
'CLF': 0.0,
'XS2239553048': 0.25},
'time_step_3': {'8801.T': 0.3939393939393939,
'ITX.MC': 0.09090909090909091,
'META': 0.12121212121212122,
'GBPJPY=X': 0.18181818181818182,
'TMBMKDE-10Y': 0.0,
'CLF': 0.0,
'XS2239553048': 0.21212121212121213}}

その後、メタデータを使用して、サンプリングされたすべての戦略の結果にアクセスできます。これにより、オプティマイザーが返した代替トラジェクトリーをさらに分析することができます。これを行うには、dpo_result['metadata']['all_samples_metrics']に格納されている辞書を読み込んでください。この辞書には、最適戦略に関する追加情報だけでなく、最適化中に評価された他の候補戦略の詳細も含まれています。

以下の例では、pandasを使用してこの情報を読み取り、最適戦略に関連する主要なメトリクスを抽出する方法を示しています。これらには、制約偏差、シャープ比、および対応する投資リターンが含まれます。

# Convert metadata to a DataFrame
df = pd.DataFrame(dpo_result["metadata"]["all_samples_metrics"])

# Find the minimum objective cost
min_cost = df["objective_costs"].min()
print(f"Minimum Objective Cost Found: {min_cost:.2f}")

# Extract the row with the lowest cost
best_row = df[df["objective_costs"] == min_cost].iloc[0]

# Display the results associated with the best solution
print("Best Solution:")
print(f" - Restriction Deviation: {best_row['rest_breaches']}%")
print(f" - Sharpe Ratio: {best_row['sharpe_ratios']:.2f}")
print(f" - Return: {best_row['returns']}")
Minimum Objective Cost Found: -3.78
Best Solution:
- Restriction Deviation: 40.0
- Sharpe Ratio: 24.82
- Return: 0.46

6. パフォーマンス分析

最後に、最適化アプリケーションのパフォーマンスを分析します。具体的には、前の例で得られた結果をランダムベースラインと比較して、このアプローチの有効性を評価します。量子アルゴリズムが一貫してより低いコスト値の結果を出す場合、それは効果的な最適化プロセスを示しています。

この図は目的コストの確率分布を示しています。これらの分布を生成するには、関数の結果から目的コストのリストを取得し、各コスト値の出現回数をカウントします(値は小数点以下2桁に丸められます)。その後、同一の丸められた値のカウントを結合することでカウント列を更新します。なお、視覚的な比較のために、出現カウントは各分布が0から1の間で表示されるように正規化されています。 最適化の解の可視化 図に示されているように(青い実線)、変分量子固有値ソルバー(SQDによるポストプロセッシング)アプローチのコスト分布は、より低い目的コスト値に鋭く集中しており、良好な最適化パフォーマンスを示しています。対照的に、ノイジーなベースラインはより広い分布を示し、より高いコスト値を中心としています。灰色の破線の垂直線はランダム分布の平均値を表しており、最適化された投資戦略を返す関数の一貫性をさらに強調しています。追加の比較として、図中の黒い破線はGurobiオプティマイザー(無料版)で得られた解に対応しています。これらの結果はすべて、「Tailored」アンザッツで評価された「Mixed Assets」の例についての以下のベンチマークでさらに検討されています。

ベンチマーク

この関数は、分解量子ビット、アンザッツ回路、およびさまざまなセクターからの資産グループの異なる設定でテストされました:さまざまな資産の混合(セット1)、石油デリバティブ(セット2)、およびIBEX35(セット3)。詳細は以下の表を参照してください。

セット日付資産
セット101/01/20238801.T, CL=F, GBPJPY=X, ITX.MC, META, TMBMKDE-10Y, XS2239553048
セット201/06/2023CL=F, BZ=F, HO=F, NG=F, XOM, RB=F, 2222.SR
セット301/11/2022ACS.MC, ITX.MC, FER.MC, ELE.MC, SCYR.MC, AENA.MC, AMS.MC

解の品質を評価するために2つの主要なメトリクスが使用されました。

  1. 目的コスト。各実験のコスト関数値をGurobi(無料版)の結果と比較することで最適化効率を測定します。
  2. シャープ比。各ポートフォリオのリスク調整後リターンを捉え、解の金融パフォーマンスへの洞察を提供します。

これらのメトリクスを組み合わせることで、量子生成ポートフォリオの計算面と金融面の両方をベンチマークします。

量子ビットアンザッツ深度ランタイム使用量(秒)総使用量(秒)目的コストシャープGurobi目的コストGurobiシャープF
Mixed Assets(セット1、4タイムステップ、4ビット)112Tailored831273513095-3.7824.82-4.2524.71
Mixed Assets(セット1、4タイムステップ、4タイムステップ、4ビット)112Real Amplitudes3591173911903-3.3923.64-4.2524.71
Oil Derivatives(セット2、4タイムステップ、3ビット)84Optimized Real Amplitudes7861806350-3.7319.13-4.1921.71
IBEX35(セット3、4タイムステップ、2ビット)56Optimized Real Amplitudes9633143523-3.6714.48-4.1116.44

結果は、問題固有のアンザッツを使用した量子オプティマイザーが、さまざまなポートフォリオタイプにわたって効率的な投資戦略を効果的に識別することを示しています。 以下に、optimizer_options辞書で指定された集団サイズと世代数の両方を詳述します。その他のすべてのパラメーターはデフォルト値に設定されています。

population_sizenum_generations
Mixed Assets Portfolio9020
Mixed Assets Portfolio9220
Oil Derivatives Portfolio12020
IBEX35 Portfolio4020

世代数は20に設定されました。この値で収束に達するのに十分であることが確認されたためです。また、オプティマイザーの内部パラメーターのデフォルト値は変更されていません。これらは一貫して良好なパフォーマンスを提供し、一般的にLiteratureおよび実装ガイドラインで推奨されているためです。

サポートを受ける

ヘルプが必要な場合は、qpo.support@globaldataquantum.comにメールを送信してください。メッセージには関数のジョブIDを記載してください。

次のステップ

推奨事項