QuantXで初期化関数を準備できたらあとは実際に売買の管理をする関数(日ごとの処理をする関数)を準備すれば基本システムは完成します。基本構造で示したように売買ハンドリングは予め決められた関数(def handle_signals(ctx, date, current):)を用意することになっているためその関数の内容をつくっていくことになります。
売買ハンドリング関数の引数
売買ハンドリング関数には3つの引数があります。
ctx
現在の状況を管理しているオブジェクトです。使用している変数名は初期化関数のものと同じですが内容は異なります(売買ハンドリング関数内でのみセット・保持される値があります)。以下のメソッドやプロパティを持ちます。
ctx.getSecurity(sym)
sym=銘柄コードに対応したSecurityオブジェクト(銘柄データのオブジェクト)を取得します。このオブジェクトを利用して売買注文を出します。Security オブジェクトによる売買注文の方法は多岐に渡るため別途説明します。
ctx.portfolio
ポートフォリオを管理するPortfolioオブジェクトです。各銘柄ごとのdict(portfolio.positions : dict)で keyのsymbol事に以下のdictを保持しています。
{
"amount": asset.amount, # 保有株数
"avg_entry_price": xxx, # 平均エントリ価格
"position_ratio": position_ratio, # 保有銘柄の中での割合,
"portfolio_ratio": portfolio_ratio,# 資産全体での割合
"pnl": xxx, # 損益額
"returns": returns # 損益率
"max_returns": max_returns # 最大損益
"holding_period": xxx # 銘柄保有営業日数。注文約定日が1
}
ctx.localStorage
次回handle_signals()が呼び出された時に保存しておきたいデータを保存しておく。ここに設定した値は、次回以降も設定されたままでhandle_signals()が呼び出される。格納オブジェクトは、Serializableであることが必要とのことです。細かい使い方は別記事とします。
date
datetime.datetime型の日付データです。(売買等の判定をする)日付が指定されます。
current
上記dateに対応する当日のデータとシグナル(売買シグナル関数の返値)を含んだ pandas.DataFrame オブジェクトです。
売買ハンドリング関数の構造
売買判定を行うアルゴリズムに応じて実装方法は異なりますが、通常は保有しているポジションに応じた処理(例えば保有してX日経過したらシグナルに関係なく手仕舞いするとか、保有ポジションの利益率がX%になったら利食いあるいは損切する)と売買シグナル関数で発生した売買シグナルに応じた処理(買いシグナルがでていたら買い)を作成します。もちろん、双方を組み合わせたて保有ポジションの株に売りシグナルが出たら売却するという処理もありえます。いずれにしても、保有ポジションや売買シグナルをチェックして、売買を行うという構造です。
このとき売買判定後の注文パターンの一例は以下のようになります。どのような売買でも基本処理は概ね一緒です。注文用の命令や引数を希望にあわせて変更することになります。
# 対象銘柄のSecurityオブジェクトを取得する
sec = ctx.getSecurity(sym)
# Securityオブジェクトを使用して売買する(売買関数は色々あるがほぼ同じ構成)
# 第一引数は売買量(プラスで買い、マイナスで売り。以下は関数が上限金額で売買する関数)
# 引数order_typeは注文タイプ(以下は始値で取引)
# 引数commentは売買のコメント(履歴を見たときに内容の確認ができる。)
sec.order_value(ctx.portfolio.cash / 2, order_type=maron.OrderType.MARKET_OPEN, comment="BUY")
ここまでの処理で過去データに対して売買処理が(仮想的に)行われて損益シミュレートがされることになります。
具体的な売買ハンドリング処理は、売買シグナルの生成とセットで別途記載します。
売買命令の関数
Securityオブジェクトを取得した後に売買を行う命令には以下の種類があります。引数は基本的にすべて同じで、第1引数の注文数の指定方法だけが異なります。第1引数がプラスの場合は買い注文を、マイナスの場合は売り注文を表します。売買単位は自動的に単元数で調整されます。注文数以外の引数については別途売買命令の引数の項目で説明します。sec = ctx.getSecurity(sym) により銘柄コード sym に対応したSecurityオブジェクトがsecに代入されているとした場合、各売買命令は、sec.売買命令(引数) という形で使用します。各命令関数はSecurityオブジェクトのメソッドです。
order
数量を指定して注文を行なう。第1引数は株数です。
order_value
金額を指定して注文を行う。第1引数は金額で、指定された金額内で購入(売却)可能な株数が設定されます。
order_percent
この銘柄の総資産評価額(現金+保有ポジション評価額)に対する割合を指定して注文を行う。第1引数は割合(<1)。0.3なら30%を表す。
order_target
この銘柄の総保有数を指定して注文を行なう。第1引数は総保有数。現在の保有数との差分が計算・注文される。
order_target_value
この銘柄の総保有金額を指定して注文を行なう。第1引数は総保有金額。現在の金額との差分が計算・注文される
order_target_percent
この銘柄の総保有額が総資産評価額(現金+保有ポジション評価額)に対して指定の割合となるように計算・注文される
売買命令の引数(第1引数以外)
各売買命令の第1引数以外は以下のようになっています。
引数 | 型 | 内容 |
comment | String | バックテスト時に出力される売買のコメント |
order_type | maron.OrderType | 注文を約定させるタイミング。デフォルト(無視定時)は、OrderType.OPEN_PRICE(始値) OrderType.MARKET_CLOSE(終値)、OrderType.LIMIT(指値), OrderType.STOP_LIMIT(逆指値)が指定できる。 |
limit_price | number | order_type が指値系(OrderType.LIMIT, OrderType.STOP_LIMIT)のときの指値。 |
limit_price_on_close | number | order_type が指値系のときの、引け指値。※引け指値は一般的に大引け、前引けのみ有効な指し値注文だが、前引け時に適用されているかは不明。 |
stop_limit_price_on_close | number | order_type が指値系のときの、引け逆指値。 |
まとめ
・売買の実行管理処理として売買ハンドリング関数 handle_signals を定義する(引数などは決まっている)
・handle_signalsは、現在の各状態、日にち、売買シグナルが引数として渡されて日ごとに呼ばれる
・取引する銘柄のSecurityオブジェクトを取得してメソッドとして売買命令を記載する
・売買命令は複数種類あるが引数は基本的に同じ構成。売買量については株数、金額、ポートフォリオ内での割合などが直接もしくは全体内での目標値で指定できる。