COVID-19パンデミック時、金融市場はどうなるのか?クオンツの分析

  • URLをコピーしました!

COVID-19は、私たちの生活のほぼすべての側面に影響を与えています。恐怖と不確実性が世界の金融市場と暗号通貨を揺さぶっています。自己検疫は、私たちの生活や社会的な交流を遅らせる。しかし、良い面では、私たちはあらゆる種類の情報を消費する時間が増えています。そこで、この機会に直近の出来事を時系列で簡単に分析したものを提供したいと思います。

次のブログでは、Pythonを使用して定量的な観点から現在の市場環境の概要を把握する方法を紹介します。私たちは、KaggleからのCOVIDデータセット、Crypto Currencyマーケットと伝統的なアセットクラスデータを探索します。これは決して科学的な論文ではなく、概念やアイデアを説明するものです。

より正確には、以下で利用可能なCorona Virusのデータセットを使用します。

カグル を使用して、各国でのウイルスの発生を可視化しました。次のステップとして、私たちは以下のサイトから暗号通貨データを見てみます。 バイナンス は、極端なボラティリティと危機の時代に共通するいくつかの定型的な事実を検証する。次に、これらの効果を伝統的な資産クラス(YahooFinance).最後に、暗号通貨市場の相関分析を行い、「伝染」は主に安定したコインへの安全逃避によって引き起こされていることを示します。

目次

ビジュアライジング COVIDデータセット

の日次データセットを使用する。 Kaggle を使用して、確定したコロナ症例数とその増加率を可視化します。アルファベット順に以下の国・地域のデータポイントに着目しています。

  • オーストリア
  • フランス
  • ドイツ
  • イタリア
  • 中国大陸
  • 韓国
  • スペイン
  • イギリス
  • 米国

この国・地域の選択は、発生の深刻さと世界経済にとっての重要性に基づいています(非常に主観的なものです)。

確定症例の数と増加率を見た後、どのレベルで強い市場補正が起こったかを見るために、観測日ごとの公式感染者数(確定症例-回復症例)も計算した(ブラックマンデーとブラックサーズデー).

始める前に、データや時系列解析によく使われるパッケージをロードします。現在サポートしているのは numpypandas 自分たちの中で トラリティ編集部.私たちは matplotib とし seaborn を使えば、より高度なチャート作成が可能です。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import seaborn as sns

これで、COVIDデータセットを探索する準備が整いました。

dataset = pd.read_csv("https://static.trality.com/blog/covid19/covid_19_data.csv")
columns = ['SNo', 'ObservationDate', 'State', 'Country',
           'Last Update', 'Confirmed', 'Deaths', 'Recovered']
dataset.columns = columns
dataset.head()

Kaggleに記載されているように、該当の列は以下のような解釈となります。

  • スノ – シリアルナンバー
  • 観測日 – 観測日(MM/DD/YYYY)
  • 州/都道府県 – 観測地点の都道府県(見つからない場合は空欄でも可)
  • 国/地域 – 観測国
  • 最終更新日 – 指定された県または国の行が更新されたUTCでの時間。(標準化されていないので、使用する前にクリーニングしてください)
  • 確認済み – 現在までの累計確認症例数
  • 死亡者数 – それまでの累積死亡者数
  • 回収数 – 現在までの累計回収件数

Kaggleの説明にもあるように、実際の症例数(確定、回復、死亡)は該当する観測日より遅れている可能性があります。デモのために、我々はとにかくObservationDateにこだわります。

ウイルスの発生を視覚化するために、まずデータを変換して、確認されたケース、回復したケース、および死亡の時系列を得ます。これを行うために、選択された国のすべての時系列を辞書で返す簡単なヘルパー関数を書きます。

def get_corona_timeseries(dataset,selcountries=None,
						  group="Country"):
    
    tsnames = ["Confirmed","Deaths","Recovered"]
    
    if not selcountries is None:
        selidx = [True if country in selcountries else False 
                  for country in dataset["Country"]]
        dataset = dataset.loc[selidx]

    tsdata = dataset.groupby(["ObservationDate",group])
    results = {}
    
    for name in tsnames:
        tmpres = {}
        series = tsdata[name].sum().reset_index()
        series = series.pivot(index="ObservationDate",
                              columns=group,values=name)
        series.index = pd.DatetimeIndex(series.index)
        tmpres["series"] = series
        growth = (1+series.pct_change().dropna()).cumprod()
        growth.iloc[0,0] = 1
        tmpres["growth"] = growth
        
        results[name] = tmpres

    return results

に準拠するために DRY プリンシパルでは、プロットのために別のユーティリティ関数を使用します。

def corona_plotter(data,ylabel,title,
				   xlabel="Observation Date",
                   figsize=(10,4)):
    fig, ax = plt.subplots(figsize=figsize)
    ax.set(xlabel=xlabel,ylabel=ylabel,title=title)
    ax.xaxis.set_major_locator(mdates.WeekdayLocator())
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d'))
    data.plot(ax=ax)
    plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))
    
selcountries = ["Germany","France","US","UK",
                "Mainland China","Italy","Austria","Spain",
                "South Korea"]
results = get_corona_timeseries(dataset,selcountries=selcountries)

まず、選択した国について、観測日ごとのコロナ確定症例数を見ることから始める。

confirmed = results["Confirmed"]["series"]
corona_plotter(confirmed,ylabel="Confirmed Cases",
			   title="Total Number confirmed cases")

明らかに中国が最も多く確認されている。しかし、成長率で見ると、ヨーロッパはずっと悪い。

confirmedGrowth = results["Confirmed"]["growth"]
corona_plotter(confirmedGrowth,
				ylabel="Confirmed Growth",
                title="Growth rates of Confirmed Cases")

最後に、観測日ごとの「公式」感染者数(確定-回復)を計算する。実際の感染者数は公式報告よりはるかに多いとしても、どの程度のレベルで市場が売れ始めたかを見るのは興味深いことである。中国はすでに感染者数が減少しているため、ここでは除外している。

infected = (results["Confirmed"]["series"] 
			- results["Recovered"]["series"])

# removing china
selcols = [col for col in infected.columns 
			if col!="Mainland China"]
            
totalinfected = infected[selcols].sum(axis=1)
# transforming dates - quick fix for annotation
totalinfected.index = [pd.Timestamp(str(date.date())) 
					   for date in totalinfected.index] 

title = """Total of confirmed Infected 
			per Observation Date 
			without China (excluding Recovered)"""

corona_plotter(totalinfected,ylabel="Infected people",
               title=title)

ブラックマンデーに、私たちが選んだ国の公式感染者数は20,000人以上に達しました。黒い木曜日には、この数は27.000人以上に増加しました。 3月22日現在、その数は164,000人を超えています。

このような伝染の劇的な効果は、数学的モデリングの観点からも研究されている。感染症のモデル化で最も単純なアプローチの1つが SIRモデル.

Crypto Currencyデータセットの探索

から取得したこのデータセットは バイナンスは、毎日の価格を含み、2019年の初めから現在(2020.03.20)までの範囲です。引用通貨USDT、BTC、EURの14の主要なシンボルを考慮しています。ブラックマンデーと木曜日の取引の大部分はUSDTのペアに影響を与えたので、分析に安定したコインを含めることは自然なことだと思われます。

各シンボルのデータは互いに積み重ねられ、以下のように構成されています。 alldata.その構造を見るために、最初の5行を表示する。

alldata = pd.read_csv("https://static.trality.com/blog/covid19/crypto_data_1d.csv")
alldata.head()

ここでは、異なるシンボルのオープン、ハイ、ロー、クローズ、ボリューム、トレードのデータを日次で表示します。 closetime は日足間隔の終値(UTC+2)を示します。

さて、積み重ねられたデータセットを見たところで、すべての通貨ペアの価格、取引量、取引を切り分けたいと思います。単純化するために、結果を tsdata の辞書に格納します。

tsdata = {}
for field in ["close","volume","trades"]:
    data = alldata.pivot(values=field,index="closetime",
    					columns="symbol").dropna()
    data = data.astype("float64")
    data.index = pd.DatetimeIndex(data.index)
    tsdata[field] = data

次のステップでは、2020年3月の通貨ペアの価格推移を見ます。

Crypto価格への重いコロナの影響

通貨間の価格に対するコロナウイルスの影響を比較できるようにするため、3月初旬からの通貨ペアの時系列を正規化し、シンボルで平均化しています。

returns = tsdata["close"].pct_change().dropna()
covidret = returns["2020-03"]
normdata = (1+covidret).cumprod()
normdata.iloc[0] = 1
meanhist = normdata.mean(axis=1)

この時系列をプロットし、ブラックマンデーと木曜日を注釈することができます。

fig, ax = plt.subplots(figsize=(10, 4))


blackmonday = normdata["2020-03-09"].index[0]
blackthursday = normdata["2020-03-13":].index[0]
price1 = normdata["2020-03-09":].iloc[0,0]
price2 = normdata["2020-03-13":].iloc[0,0]


meanhist.plot(ax=ax)

title = 'Average Markt Evolution March 2020 - normalized'
ax.set(title=title,
       ylabel='Normalized Values',
       xlabel="Date")

ax.annotate('Black Monday',
            xy=(blackmonday, price1),
            xycoords='data',
            xytext=(30,30),
            textcoords='offset points',
            arrowprops=dict(headwidth=10, 
            width=3, color='#363d46',
            connectionstyle="angle3,angleA=0,angleB=-90"),
            fontsize=12)

ax.annotate('Black Thursday',
            xy=(blackthursday, price2),
            xycoords='data',
            xytext=(10,30),
            textcoords='offset points',
            arrowprops=dict(headwidth=10, 
            width=3, color='#363d46',
            connectionstyle="angle3,angleA=0,angleB=-90"),
            fontsize=12)


見てわかるように、暗号市場の最初の打撃は3月9日(ブラックマンデー)ごろに始まりました。 暗号市場の本当の伝染は3月13日の暗黒の木曜日から始まり、いくつかの通貨ペアは50%以上下落しました。平均的な市場は、3月の初めからその価値の30%以上を失いました。

セルオフ時の出来高急増

恐怖と不確実性も取引量に大きな影響を与え、一般的に価格変動と反比例しています。出来高データを標準化するために 最小-最大 スケーラーを使用します。こうすることで、異なる測定単位やレベル依存性の問題を回避することができる。ここでもまた、取引量の平均をとります。見てわかるように、取引量の急増は平均価格の下落と一致します。

volume = tsdata["volume"]
normvol = (volume-volume.min())/(volume.max()-volume.min())
covidvolume = normvol["2020-03":]

covidvolume.mean(axis=1).plot(figsize=(10,4),
							title="Average Scaled Volume")

苦境に陥った時の相場の乱高下

金融リターンの一つの特徴は、市場の苦難の時期には極端な市場の動きが続く傾向があることです。この現象は、次のように知られています。 ボラティリティ・クラスタリング.その結果は、ファイナンスでよく使われるいくつかの仮定が崩れ、特に正規性の仮定が崩れるなど、広範囲に及びます。詳細な説明については、この論文を参照してください。 資産リターン.

通常、絶対リターンをプロットすることで、ボラティリティのクラスタリングを検査することができます。絶対収益率が高いのは、市場にストレスがかかっている時期に集中する。クラスターとして現れる。

returns.abs().plot(figsize=(10,4),
			title="Absolute Returns Currencies")
plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))

歴史がまだ十分でないにもかかわらず、私たちはクラスター化の最初の兆候を見ており、この状況はしばらくの間続く可能性が非常に高いと思われます。

伝統的なアセットクラスを探る

このセクションでは、伝統的な資産クラスの価格時系列を見ます。データセットは、コモディティ、インデックス、通貨からの様々な時系列で構成されています。

  • コモディティ:金、原油
  • インデックス:S&P指数(米国)、30y国債利回り(米国)、ハンセン指数(中国)、SX5E(欧州)、FTSE(英国)
  • 通貨:EURUSD通貨、GBPUSD通貨

このデータセットは、以下の日次価格データから構成されています。 YahooFinance.

YahooFinanceには、オープン、ハイ、ロー、クローズ、出来高のデータも含まれています。フィールドティッカーは、それぞれのコモディティ、インデックス、または通貨を表します。これらの時系列は直接取引される商品を表すものではないので、出来高データは無視しています。

商品市場、株式市場で強いヒット

暗号通貨のデータと同様に、伝統的な資産クラスの市場に対する平均的な価格の影響を見てみましょう。

alldata2 =pd.read_csv("https://static.trality.com/blog/covid19/traditional_assets_daily.csv
")

tsdata2 = {}
for field in ["close","volume"]:
    data=alldata2.pivot(values=field,
    					index="date",
                        columns="ticker").dropna()
    data = data.astype("float64")
    data.index = pd.DatetimeIndex(data.index)
    tsdata2[field] = data

再び伝統的な資産の時系列を正規化し、2020年3月の展開を強調します。

returns2 = tsdata2["close"].pct_change().dropna()
covidret2 = returns2["2020":]
normdata2 = (1+covidret2).cumprod()
normdata2.iloc[0] = 1

fig, ax = plt.subplots(figsize=(10, 4))

oilprice = normdata2.loc[blackmonday.date(),"OIL"]


# highlight march period
ax.axvspan(normdata2["2020-03"].index[0], 
			normdata2["2020-03"].index[-1], 
			color='grey', alpha=0.5)
normdata2.plot(ax=ax)

ax.set(title='Normalized timeseries Asset Classes',
       ylabel='Normalized Values',xlabel="Date")



ax.annotate('Corona/Oil War',
            xy=(blackmonday, oilprice),
            xycoords='data',
            xytext=(-10,-30),
            textcoords='offset points',
            arrowprops=dict(headwidth=10, 
            width=3, color='#363d46',
            connectionstyle="angle3,angleA=0,angleB=-90"),
            fontsize=12)

plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))

暗号通貨のデータセットが1つの市場しか表していないのとは対照的に、ここでは非常に多様な市場を見ています。しかし、3月の時点で、ほとんどの資産クラスが同じ方向に動いており、もちろん債券利回りは例外です。 債券利回りは価格と逆相関の関係にあります.

価格の乱高下はすべての資産クラスに影響する

伝統的な資産クラスの絶対リターンをプロットすると、ボラティリティのクラスタリング効果も示されます。

returns2["2019":].abs().plot(title="Absolute Returns")
plt.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))

拡大するウイルスとその結果に対する恐怖は、伝統的な市場と暗号通貨市場の両方に同じように感染したようです。少なくとも、一見したところ、価格とボラティリティに同様の反応が見られます。

暗号通貨における相関とスピルオーバー

暗号通貨における高い相関性については、多くの報道がなされています。その バイナンスのレポート 2019年はCrypto Marketの中央値相関が引き続き高い状態であると述べています。また、人気メディアも懸念しているようです。 コインテレグラフは、例えば、BTCがETHに与える影響とその逆について述べています。因果関係と相関関係の誤解は別として、BTCとETHの関係について2つの対立する見解を示しています。時系列における依存関係の推定には、多くの課題があります( UCLリサーチノート).

コロナ危機の暗号への影響は、安全への逃避をもたらしました。その結果、安定したコインペアとBTCペアの間で異なる平均相関が見られると予想される。 その指標を得るために、データを2つのセットに分けました。1 つのセットには安定した基本通貨 (USDT, EUR) のすべてのペアが含まれ、もう 1 つのセットには BTC のペアが含まれています。

時系列の依存性を推定する問題を軽減するために、ローリング相関を監視し、ローリング期間のすべてのウィンドウでリターンをデトレンドすることができます(参照) 暗号通貨における伝染).我々の目的では、それぞれのウィンドウのすべてのリターン時系列をトレンド除去するのではなく、単純に正規化します。このために、私たちは小さなヘルパー関数を作成します。

def avg_rolling_correlation(data,window=10):
        
    if not isinstance(data,pd.DataFrame):
        raise TypeError("only dataframes supported!")
    
    timestamps = data.index
    result = pd.Series(index=timestamps)
    
    windows = zip(timestamps[:-window],timestamps[window:])
    
    for start,end in windows:
        tmpdata = data.loc[start:end]
        normdata = (tmpdata-tmpdata.mean())/tmpdata.std()
        meancorr = normdata.corr().values.mean()
        result[end] = meancorr

    return result

次に、両方のセットのローリング相関を計算し、結果をプロットします。

selcols = [col for col in returns.columns if (col[-4:]=="USDT" or col[-3:]=="EUR")]
stableCorr = avg_rolling_correlation(returns[selcols]).dropna()
stableCorr.name="stable coins"


selcols2 = [col for col in returns.columns if col not in selcol]
otherCorr = avg_rolling_correlation(returns[selcols2]).dropna()
otherCorr.name = "BTC"

corrdata = stableCorr.to_frame()
corrdata = corrdata.merge(otherCorr
                            ,on="closetime",how="inner")

print(selcols2)
ax = corrdata.plot()

ax.set_title("Average correlations in stable coin vs BTC pairs")
ax.set_ylabel("Average Correlation")

上記の結論として、市場における極めて高い相関は、主に安定したコインへの安全逃避によって引き起こされたと思われます。流動性不安などがこの状況を悪化させたのかもしれません。他の通貨ペアは、相関関係が低く、早く通常のレベルに戻るかもしれません。

経験的に、相関関係のローリングは、かなり先の市場センチメントを示す良い指標となる傾向があります。その平均回帰的な性質から、取引において幅広い用途があります。

バイアスを避けるための定量的分析

危機的な状況は、暗号通貨だけでなく、伝統的な資産クラスで観察することができる典型的な市場のパターンになることがよくあります。これらのパターンを分析し理解するために必要な情報のほとんどは公開されており、簡単に取り出すことができるため、定量分析はそれを理解するための強力なツールとなります。 上記の分析から得られる主なポイントは以下の通りです。

  • 価格と出来高は負の相関を持つ傾向がある。高い取引量は一般的に価格の下落と関連している。誰もが同時に抜け出したいと思っている。
  • パニックがさらにパニックを引き起こす。高い価格変動が続く傾向がある。ボラティリティの観点からは、クラスタリング効果を観察することができる。
  • 安全への逃避により、安定したコインペアの平均相関は非常に高い水準に達している。BTCペアの相関ははるかに低く、早く安定するようだ。
  • Pythonはクールだからもっと使うべき

楽しんでいただけたでしょうか?もし何かご意見やご提案があれば、私たちにお知らせください。私たちにメールを送ってください。 [email protected].

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次