2022.04.05

カモにならないアルゴリズム取引:取引コストと戦略入門編

こんにちは。次世代システム研究室のK.S.(女性、外国人)です。

みなさん、コロナ禍の生活に慣れてきて、いかがですか?。色々な感想があると思います。「もううんざり!」「お家時間それなりに楽しんでいるよ」「アフターコロナはどうなる?」等。世界は、コロナ危機から回復しつつあり、2022年に入って米国の利上げなどの金融政策で、経済活動も段階的に再開されてきました。一方、刻々と変化する世界情勢のもと、金融市場は乱高下(相場が短期間で上がり下がりの変化が激しく繰り返し)しやすい状況になっています。

それゆえ、今こそ、投資の好機と考え、小遣い稼ぎができればいいなあとふと思ったりしませんか。ただ、運に頼るのではなく、乱高下の状況でもきちんとリスク管理した上で、安定的に、儲けられるようにすることが必要です。そのため、基本知識から少しずつ理解しながら、楽しく取引(トレーディング)できればと思っています。

ということで、カモにならないトレーディング入門を始め、アルゴリズム取引の連載ブログを書いていくつもりです。楽しくお付き合い頂ければと思います。どうぞよろしくお願いします。

1. アルゴリズム取引(Algorithmic Trading)とは?

アルゴリズム取引(Algorithmic Trading, 自動取引)「以下、アルゴ取引」は定義されたアルゴリズムに従うコンピュータープログラムを使用して取引(トレーディング)を行うことです。理論的に、タイミング、価格、数量、数式モデルのような要因に基づいて、コンピューターが人間には不可能な速度と頻度で利益を生み出す事です。

今回はアルゴリズム取引を行うため、「取引アルゴリズム」、「取引手法」、「投資サイクル」といった基本知識を紹介したいと思います。

1.1.取引アルゴリズムについて

取引アルゴリズムは主に三つあり、1. Execution Algorithms(実行アルゴリズム)、2. Profit Seeking Algorithms(利益追求アルゴリズム)、3.High Frequency Trading Algorithms(高頻度取引アルゴリズム)があります。「1.実行アルゴリズム」はポートフォリオマネージャー(預かった顧客の資産をふさわしい方法で投資・運用する責任を負う人)が投資目的を達成するために指定したルールに従って取引します。「2.利益追求アルゴリズム」はリアルタイムの市場データを使用して、売買する証券を決定し、これらの取引を可能な限り効率的に実行します。「3.高頻度取引アルゴリズム」は2.のやり方での短期間取引になります。今回ブログでは「1.と2.」を中心に話します。

1.2.取引手法について

取引については、商品(株式、外国為替、など)によって、細かい注文手法がありますが、大体どんな取引でも、主に3つの注文手法があり、market order(成行)、limit order(指値)、stop limit order(逆指値)です。
  1. market order(成行注文)は自分で売買価格を指定しなくても、市場が開いていれば、ask(売り気配値)やbid(買い気配値)の値段で売買が約定されます。
  2. limit order(指値注文)は自分で売買価格を指定します。
  3. stop limit order(逆指値注文)は損切りの使い方として、通常の成行や指値とは逆に、指定した価格以上になったら買付、以下になったら売付の注文を発注します。

1.3.投資サイクルについて

アルゴ取引で大事なことは、アルゴリズムが投資目的と一致する注文を実行しているかを確認することです。そのため、アルゴリズムを利用し、投資サイクルで投資を繰り返しながら儲かるかを評価します。投資サイクルは4つのステップがあり、①Asset Allocation(アセットアロケーション、資産管理), ②Portfolio Construction(ポートフォリオ構築), ③Implementation(実行), ④Portfolio Attribution(ポートフォリオアトリビューション)です。一般的に、この4つを繰り返し資産を運用していきます。

具体的には、①アセットアロケーションによって、資金のリスクコントロールの範囲で、効率的なリターン(利益率)を考えた上で、資産(アセット)を配分(アロケーション)します。②ポートフォリオ構築によって、資金内で、ふさわしい商品(株式・債券・不動産・外貨建て商品・現金など)を組み合わせます。③選択された商品についての取引を実行します。④投資のパーフォーマンスを測定します。

では、利益を生むために、①と②で商品を組み合わせた後、③で執行するときに、どのようなコストが発生するのか、④でどうやってパーフォーマンスを測定するか、を中心に紹介します。

2. 執行コスト(Transaction Costs)

執行コストとは、証券の売買取引に関わるコストです。このセクションでは執行コストの分類とコスト測定(Implementation shortfall)を紹介します。

2.1. 執行コストの分類

執行コストは主に二つの分類で分けられ、直接コストと間接コストです。直接コストは各種取扱手数料や税金などのコストです。間接コストは取引で価格の変動に関わるコストです。それぞれのコストの詳細は下記になります。
  • 直接コスト:
    • 各種取扱手数料(commission, fee)
    • 税金(tax)
    • 割引(リベート、rebates)
  • 間接コスト:
    • スプレッド(spread):買値と売値の差。市場価格の急変時や市場の流動性が低下している状況においては拡大する場合があり、想定よりコストが高くなる可能性があります。
    • 遅延コスト(delay cost):発注してから、約定までの時間差で価格が変動することによって発生するコスト
    • 価格の増価(price appreciation):一定期間にわたる価格の増加
    • マーケットインパクト(market impact):自分の取引(売買)で、価格を不利にすることで発生するコスト
    • タイミングコスト(timing risk):売買案件を策定から市場へ発注するまでの間に価格が変動することによって発生するコスト
    • 機会コスト(opportunity cost):未約定で残ってしまった証券の価格が変動することによって発生するコスト
直接コストは簡単に計算できますが、間接コストの算出は難しいです。しかし、執行コスト分析を行うことにより、運用パフォーマンスを最大化することが期待できます。執行した取引が問題ないかを評価し、それに基づいて改善していきます。分析手法は沢山ありますが、今回はよく使われている方法(Implementation Shortfall)を紹介します。

2.2. Implementation Shortfall (IS)

Implementation Shortfall (以下、IS)は執行コストを抑えることを目的として、執行コストを測定するための手法です。ISは直接コストと間接コストを分解し、間接コストも細かく分解します。ISではpaper return(想定上の損益)とactual return(実際の損益)の差を計算します。paper returnは全てのシェアが決定された価格で執行されると仮定し計算します。actual returnは実際に執行されたシェアと価格を計算します。たびたび、利益を得る機会を逃したことと同様に、取引の執行に関連する摩擦と説明されます。業界によって、ISはSlippage(スリッページ)と呼ぶこともあります。数式は下記になります。


式によると、ISはPaper ReturnとActual Returnの差で、Paper Returnは最後と最初のプライスの差です。S(share)は全ての取引したいシェア、Pd(decision price)は決定したプライス、Pn(price at end period)最後の時間(N)のプライス(終値)です。Actual Returnは手数料を引いた実際に取引した価格です。sjとpjは取引ごとのシェアとその時のプライスです。また、下記のある式、Pavg(average price)は取引したシェアの平均価格で、P0は発注時の価格です。

ISは主に3つの考えで提案され、下記のような式で表せます。
  • Complete execution
  • Opportunity cost (Andre Perold)
  • Expanded IS (Wayne Wagner)

Expaned Implementation Shortfallによると、遅延コスト、売買コスト、機会コスト、手数料を分解することができます。

利益を得るためには、ISを最小化し、様々な取引コスト要素をトレードオフする必要があります。大体なイメージとしては日本銀行金融研究所の論文の図がわかりやすいので、少し修正し転載させていただきます。


ISの間接コストの要素の中にあるマーケットインパクト・タイミングコスト・機会コストを最小にしようとします。マーケットインパクトは取引数量が増えると、コストが高くなる傾向があります。そのため、取引を分割し、時間をかけて執行すると、マーケットインパクトコストを抑えることができます。一方、執行時間が長くなると、価格変動でタイミングコストや機会コストが高くなってしまいます。コストを最小化するためには、その辺のバランスを考えなければならないです。これはoptimal execution strategies(最適執行戦略)と呼ばれます。

執行のコストを抑えるために、最適執行戦略がありますが、それに加えて、どのような戦略を執行したら、一番利益を生み出せるのかを明らかにするための取引戦略があります。

3. 取引戦略(Trading Strategy)

初めて投資するときに、どの商品(銘柄)に投資すべきかを決めなければなりません。銘柄が決まっても、日々の動きを観察しながら、①いつentry(購入)するか ②いつexit(決済)するか ③いつstop loss(損切り)するか、を決める必要があります。そのため、様々な取引戦略があります。

取引戦略(Trading Strategy)は銘柄の運用をするための戦略です。主な戦略は二つに分けられ、fundamental(ファンダメンタルズ)とtechnical(テクニカル)です。

ファンダメンタルズ分析は、業界、市場全体、国内および地球環境に加えて、ビジネスのあらゆる側面を評価することにより、企業の公正な価値を導き出すことです。テクニカル分析は、過去のリターンや価格変動などのデータを評価して、証券および市場全体の将来の価格変動を推定するために使用できるパターンをグラフ化することです。今回はテクニカル分析に注目します。

3.1. テクニカル分析

テクニカル分析でよく使われている指標は沢山ありますが、分類すると、trend, mean reversion, relative strength, momentum, volumeになります。
  • trend:トレンド指標は、市場が時間の経過とともに上昇、下降、または横ばいであるかどうかを分析します。
  • mean reversion: 平均回帰指標は、マーケットにおいて、いったん大きく振れた相場が平均値へ戻そうとすることです。
  • relative strength: 相対強度指標は、売買圧力の変動を測定します。
  • momentum: モメンタム指標は、時間の経過に伴う価格変動の速度を評価します。
  • volume: ボリューム指標は取引を集計し、強気または弱気がコントロールされているかどうかを定量化します。
それぞれの指標には良し悪しがあり、証券に合わせて取引するのが無難かと個人的には思います。それゆえ、安定的な運用のため、取引前に、バックテストの仕組みを利用します。バックテストは決めた売買ルールに従って、過去のデータで、取引した場合の有効性を検証することです。一定期間で期待通りに、パフォーマンスが得られるかをシミュレーションします。

4. 実装

いよいよ、実装です。

やりたいことは過去の株価データに基づいて、簡単な取引戦略をバックテストし、取引コストなどを評価してみることです。

4.1. 実装環境とデータ処理

実装環境

環境はGoogle Colaboratoryを利用しました。バックテストはbacktraderというPythonバックテストライブラリを使います。また、可視化のため、backtrader_plottingを使用し、portfolio分析のため、pyfolioを使いました。

余談ですが、Pythonでのバックテストには様々なライブラリがあります。私の記憶ベースで、よく使われているのはbacktrader, pyalgotrade, zipline, backtesting.pyです。自分の好みで、今回はbacktraderを使っています。

データセット

データセットはyahoo financeのデータを利用しました。下記のように、yahoo finance APIからデータをダウンロードし、自動的にbacktraderシステムに投入できます。これはyahoo financeに情報が入っている銘柄(株、為替、ビットコイン、など)に対応していますので、結構便利です。
import backtrader as bt
import yfinance as yf
instrument = '9449.T' # GMO株を例として
start_date = '2010-01-01' # バックテスト開始日
end_date = '2021-12-01' # バックテスト終了日
data = bt.feeds.PandasData(dataname=yf.download(instrument, start_date, end_date))
データはディリーベース取引情報のpandas dataframeです(下記の図)。中身はローソク足(1日の取引時間中の値動き情報)で、Open(始値), High(高値), Low(安値), Close(終値), Adj Close(調整後終値), Volume(取引数量)が含まれています。ローソク足については昔のブログで説明しましたので、そちらを参考ににしていただければと思います。


 

4.2. 簡単な戦略でバックテストしてみた

前提:バックテストは実際の市場状況を保証することができないので、いかにシミュレーション結果が優れていても、実際はスリッページが発生する可能性があります。

今回はある程度発生可能なコストも含めて再現してみようと思います。

SMA Crossover

まず、簡単な取引戦略を実装しました。使った戦略はトレンド指標の一つのSMA Crossoverという有名な戦略です。SMAはSimple Moving Average(単純移動平均)で単一の期間の一定数の価格を合計し、期間数でその合計を割って算出します(下記の式)。SMA Crossoverは二つの単純移動平均をクロスオーバーする指標で、売買のサインを示します。高速SMA(fastSMA、短期間)が低速SMA(SlowSMA、長期間)を超える場合、買いシグナルを示し、逆でしたら、売りシグナルを示します。

ちなみに、SMAは元の価格より遅れます。使用したい銘柄の特徴に合わせて、遅れを減らしたい場合、EMA(Exponential Moving Average、指数移動平均)を使用することもあります。


 

SMA Crossover戦略のコードは下記になります。
class SmaCrossOver(bt.Strategy):
   # list of parameters which are configurable for the strategy
   params = dict(
       pfast=10,  # period for the fast moving average
       pslow=30   # period for the slow moving average
   )
 
   def __init__(self):
       fast_sma = bt.ind.SMA(period=self.p.pfast)  # fast moving average
       slow_sma = bt.ind.SMA(period=self.p.pslow)  # slow moving average
       self.crossover = bt.ind.CrossOver(fast_sma, slow_sma)  # crossover signal
 
   def next(self):
       if not self.position:  # not in the market
           if self.crossover > 0:  # if fast crosses slow to the upside
               self.buy()  # enter long
 
       elif self.crossover < 0:  # in the market & cross to the downside
           self.close()  # close long position

Simple Mean Reversion戦略

Bollinger bands(ボリンジャーバンド)を使ってmean reversion(平均回帰指標)も簡単に実装してみました。Bollinger bandsは相場の振れ幅(ボラティリティ)を一定期間の価格データから測定し、統計学的な観点から価格の変動範囲を予測する指標です。今回はmean reversionコンセプトで、振れ幅を利用し、プライスが戻ると仮定して売買します。具体的には、entryについて、プライスがlower bandの下になったら買い、upper bandの上になったら売りにします。exitについて、プライスはmedian lineになったら決済します。


 

Simple Mean Reversion戦略のコードは下記になります。
class SimpleMeanReversion(bt.Strategy):
   params = dict( period=20, devfactor=2, size=10)
   def __init__(self):
       self.boll = bt.indicators.BollingerBands(period=self.p.period, devfactor=self.p.devfactor)
   def next(self):
       orders = self.broker.get_orders_open()
       if orders:
           for order in orders:
               self.broker.cancel(order)
       if not self.position:
           if self.data.close > self.boll.lines.top:
               self.sell(exectype=bt.Order.Stop, price=self.boll.lines.top[0], size=self.p.size)
           if self.data.close < self.boll.lines.bot: self.buy(exectype=bt.Order.Stop, price=self.boll.lines.bot[0], size=self.p.size) else: if self.position.size > 0:
               self.sell(exectype=bt.Order.Limit, price=self.boll.lines.mid[0], size=self.p.size)
           else:
               self.buy(exectype=bt.Order.Limit, price=self.boll.lines.mid[0], size=self.p.size)
 

上述のように、今回の目的は戦略のバックテストだけではなく、実際の取引に近い状況でシミュレーションをしたいです。そのため、取引戦略を行うことと、「手数料」や「スリッページ」なども加えて検証してみます。

backtraderでは、「手数料」はsetcommission、「スリッページ」はset_slippage_perc、を利用し、設定できます。バックテストコードの例は下記になります。
import yfinance as yf
import backtrader as bt
# set up engine
cerebro = bt.Cerebro()
 
# add strategy
cerebro.addstrategy(SmaCrossOver) 
 
# download data and add to backtest system (Stock names: 5269.T(Nippon Concrete), 9449.T(GMO internet))
data = bt.feeds.PandasData(dataname=yf.download('9449.T', '2010-01-01', '2021-12-01'))
cerebro.adddata(data, name="test")
 
# set cash
cerebro.broker.setcash(1000.0)
 
# set commission
cerebro.broker.setcommission(commission=0.000) # 0.001 => 0.1%
 
# set slippage
cerebro.broker.set_slippage_perc(0.000)  # 0.005 => 0.5%
 
# add analyser
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='pyfolio')
cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="trade_analyser")   
 
# print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
 
# run backtest
results = cerebro.run()
 
# analyse portfolio
strat = results[0]
pyfoliozer = strat.analyzers.getbyname('pyfolio')
returns, positions, transactions, gross_lev = pyfoliozer.get_pf_items()
 
# print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
 
# plot results
cerebro.plot(iplot=False)
上記の実行をすると、選んだ戦略でどのような取引をしたのかが確認できます。

GMO internetの例
長い期間で価格が上昇していくような例

 

日本コンクリートの例
価格の変動に周期性が見られる例

 

また、interactiveで見たいとき、backtrader_plottingがおすすめです。コードに一行を追加することで、色々な可視化結果が見られますので、便利です。
from backtrader_plotting import Bokeh
from backtrader_plotting.schemes import Tradimo
# plot backtest results
b = Bokeh(style='bar', plot_mode='single', scheme=Tradimo())
cerebro.plot(b)

4.3. コストを測定し、軽く評価してみた

上記の実装で様々なバックテスト(手数料やスリッページ有無など)を行った結果を、簡単に取引コストで比較してみます。

投資サイクルの資産運用の例として、二つのポートフォリオを構築してみました。投資は2,000円で二つの株をそれぞれ1,000円ずつに分散してみました。バックテスト期間は2010/01/01 – 2021/12/01にしました。結果は下記のようになります。SMAはSimple Moving Average戦略で、SMRはSimple Mean Reversion戦略です。


バックテスト結果によると、銘柄の特徴とトレード戦略には相性があることがわかります。個人的な直感ですが、GMOのような上がっていくトレンドですと、trend的な戦略が適応しやすいかもしれません。一方、Nippon Concreteのような季節的な影響を受けている工事関係会社はトレンドが戻ったりする可能性が高いので、mean reversion理論のような戦略が適切かもしれません。

また、トレードで儲かってても実際は手数料もかかりますし、マーケットのスリッページが大きければ、想定よりコストが発生します。この例ですと、手数料は直接的なコストですので、管理できますが、スリッページは間接的なコストであり、実際の取引時の価格の振れ範囲を想定しながら考える必要があるのではないかと思います。その辺をきちんと考慮しなければカモになってしまう可能性があります。

ついでに、ポートフォリオも紹介します。backtrader経由で、pyfolioを利用できますので、簡単に様々な指標を計算してくれます。
import pyfolio as pf
fig = pf.create_returns_tear_sheet(
   returns,
   positions=positions,
   transactions=transactions,
   live_start_date='2018-01-01',  # This date is for starting out-of-sample
   return_fig=True
   )
GMOのSMA結果を簡単に見せます。利益率(return)や最大損失(max. drawdown)を計算してくれます。また、リスク管理の評価指標(Sharpe ratio, Calmar Ratio, Omega ratio, Sortino Ratio)も出してくれます。skewnessやkurtosisなども観察できます。


 

年や月ベースのリターンなどを確認することもできます。


 

5. まとめと考察

今回は取引コスト、IS、取引戦略といったアルゴ取引の基本知識を紹介し、簡単なバックテスト実装とコスト測定を行いました。今回の記事では主に3つの点を学びました。
  1. アルゴ取引の投資はリスクがあり、簡単な実装を用いてでも金融商品の特徴が明らかにし、投資サイクルを考慮に入れ適切なポートフォリオを組み立てた方が無難なのではないか
  2. 取引コストは見えないコスト(間接的なコスト)の影響が大きく、検討する価値があるのではないか
  3. バックテストは実際の金融市場を再現できないですが、取引コストやISを計算することで、より近い状況を再現すること)期待できるのではないか

参考

  • https://www.sciencedirect.com/book/9780128156308/algorithmic-trading-methods/
  • https://www.backtrader.com/
  • https://www.ogis-ri.co.jp/rad/webmaga/rwm20110501.html
  • https://www.imes.boj.or.jp/research/papers/japanese/kk30-2-2.pdf
  • https://www.investopedia.com/articles/active-trading/011815/top-technical-indicators-rookie-traders.asp
  • https://media.axitrader.com/web-dev/dagnhe1k/axitrader-ebook3-hat-trick-3-easy-entry-exit-strategies-v2.pdf

最後に

次世代システム研究室では、ビッグデータ解析プラットホームの設計・開発を行うアーキテクトとデータサイエンティストを募集しています。興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧からご応募をお願いします。

一緒に勉強しながら楽しく働きたい方のご応募をお待ちしております。

  • Twitter
  • Facebook
  • はてなブックマークに追加

グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

 
  • AI研究開発室
  • 大阪研究開発グループ

関連記事