mirror of
https://github.com/codez0mb1e/resistance.git
synced 2024-11-24 11:22:19 +00:00
Merge pull request #19 from codez0mb1e/azure-day-conf
Currency portfolio: assets selection
This commit is contained in:
commit
e68f56d9a8
@ -23,6 +23,14 @@
|
||||
|
||||
:newspaper: **Последние обновления**:
|
||||
|
||||
Апрель 2022:
|
||||
|
||||
- Для формирования низкорискованного валютного портфеля:
|
||||
- добавил скрипт [анализа волатильности валют](src/fx_currencies_analysis.md)
|
||||
- добавил скрипт [моделирования цен валют с использованием метода Монте-Карло](src/fx_currency_portfolio__assets_selection.ipynb)
|
||||
|
||||
Март 2022:
|
||||
|
||||
- Обновление списка [стейблкоинов](lists.md#stablecoins)
|
||||
- Рефакторинг списка [VPN сервисов](lists.md#vpn)
|
||||
- Обновлена структура `README.md`
|
||||
|
11
faq.md
11
faq.md
@ -14,8 +14,15 @@
|
||||
|
||||
### Как выбрать соотношение рублей, иностранной валюты для наличных средств?
|
||||
|
||||
Оценить вероятность, что ЦБ введет фиксированный курс с одновременным запретом покупки/продажи валюты на открытом рынке.
|
||||
|
||||
Чем выше эта вероятность, тем бОльшая доля наличных средств в рублях должна быть в корзине; максимальную долю рублей имеет смысл ограничиться 80%.
|
||||
Оценить вероятность, что ЦБ введет фиксированный курс с одновременным запретом покупки/продажи валюты на открытом рынке.
|
||||
|
||||
Чем выше эта вероятность, тем бОльшая доля наличных средств в рублях должна быть в корзине; максимальную долю рублей имеет смысл ограничиться 80%.
|
||||
|
||||
Чем ниже эта вероятность, тем бОльшая доля наличных средств в иностранной валюте должна быть. Минимальная долю рубля имеет смысл ограничить 30%.
|
||||
|
||||
### Как сформировать низкорискованный валютный портфель?
|
||||
|
||||
1. [Проанализируйте волатильности валют](src/fx_currencies_analysis.md) на основе исторических данных и выберете те, риски по которым ниже рублевых.
|
||||
2. [Смоделируйте цены валют](src/fx_currency_portfolio__assets_selection.ipynb), выбранных на шаге 1, с использованием метода Монте-Карло.
|
||||
3. Основываясь на результатах моделирования, выберите наиболее подходящии Вам по соотношению доходность/риски валютные пары.
|
||||
|
188
src/cryptocurrency_portfolio__assets_selection.py
Normal file
188
src/cryptocurrency_portfolio__assets_selection.py
Normal file
@ -0,0 +1,188 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
|
||||
"""Crypto Currency Portfolio: Assets Selection.
|
||||
|
||||
Description:
|
||||
Crypto Currency Selection using monte Carlo simulation.
|
||||
"""
|
||||
|
||||
# %% Import dependencies ----
|
||||
# core
|
||||
import os
|
||||
import gc
|
||||
|
||||
# data science
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from scipy.stats import norm
|
||||
|
||||
# Cloud integration
|
||||
from azureml.core import Workspace, Dataset, VERSION as aml_version
|
||||
print(f'Azure ML SDK v{aml_version}')
|
||||
|
||||
# network
|
||||
import ssl
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
|
||||
# plots
|
||||
import matplotlib.pyplot as plt
|
||||
import seaborn as sns
|
||||
|
||||
# show info about python env
|
||||
from IPython import sys_info
|
||||
print(sys_info())
|
||||
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
# %% Set params ----
|
||||
symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'MATICUSDT', 'UNIUSDT']
|
||||
|
||||
n_days = int(252) # US market has 252 trading days in a year
|
||||
n_iterations = int(1e4)
|
||||
|
||||
|
||||
|
||||
# %% Load quotes ----
|
||||
def get_quotes(symbol: str) -> pd.DataFrame:
|
||||
df = pd.read_csv(f'https://www.cryptodatadownload.com/cdd/Binance_{symbol}_d.csv', skiprows=[0])
|
||||
df = df.set_index('date')
|
||||
df = df.sort_values(by = 'date')
|
||||
|
||||
return df[['symbol', 'open', 'high', 'low', 'close']]
|
||||
|
||||
quotes_data = [get_quotes(s) for s in symbols]
|
||||
# row-wise union:
|
||||
# pd.concat([get_quotes(s) for s in symbols])
|
||||
# column-wise:
|
||||
# pd.concat(list1, axis=1, ignore_index=False)
|
||||
|
||||
|
||||
btcusdt_df = quotes_data[0]
|
||||
|
||||
pd.concat([
|
||||
btcusdt_df['close'].head(5),
|
||||
btcusdt_df['close'].tail(5)
|
||||
])
|
||||
|
||||
|
||||
|
||||
# %% Calculate Return
|
||||
def get_returns(close_prices) -> pd.Series:
|
||||
return (close_prices/close_prices.shift()) - 1
|
||||
|
||||
|
||||
btcusdt_df['diff'] = btcusdt_df['close'].diff()
|
||||
btcusdt_df['return'] = get_returns(btcusdt_df['close'])
|
||||
|
||||
btcusdt_df[['close', 'diff', 'return']].tail(10)
|
||||
|
||||
|
||||
|
||||
# %% Calculate LogReturn
|
||||
def get_log_returns(return_prices) -> pd.Series:
|
||||
return np.log(1 + return_prices)
|
||||
|
||||
btcusdt_df['log_return'] = btcusdt_df['return'].apply(lambda x: get_log_returns(x))
|
||||
btcusdt_df[['close', 'diff', 'return', 'log_return']].tail(10)
|
||||
|
||||
|
||||
|
||||
# %% Simulate possible LogReturns
|
||||
|
||||
def get_simulated_returns(log_returns: pd.Series, n_days: int, n_iterations: int) -> pd.Series:
|
||||
u = log_returns.mean()
|
||||
var = log_returns.var()
|
||||
stdev = log_returns.std()
|
||||
|
||||
drift = u - (0.5*var)
|
||||
Z = norm.ppf(np.random.rand(n_days, n_iterations))
|
||||
|
||||
return np.exp(drift + stdev*Z)
|
||||
|
||||
|
||||
btcusd_logreturns = btcusdt_df['log_return'].dropna()
|
||||
btcusd_simulated_returns = get_simulated_returns(btcusd_logreturns, n_days, n_iterations)
|
||||
|
||||
assert(
|
||||
btcusd_simulated_returns.shape == (n_days, n_iterations)
|
||||
)
|
||||
|
||||
|
||||
|
||||
# %% Monte carlo simulation functions ----
|
||||
def get_breakeven_prob(predicted, threshold = 0):
|
||||
"""
|
||||
This function calculated the probability of a stock being above a certain threshhold, which can be defined as a value (final stock price) or return rate (percentage change)
|
||||
"""
|
||||
predicted0 = predicted.iloc[0,0]
|
||||
predicted = predicted.iloc[-1]
|
||||
predList = list(predicted)
|
||||
|
||||
over = [(i*100)/predicted0 for i in predList if ((i-predicted0)*100)/predicted0 >= threshold]
|
||||
less = [(i*100)/predicted0 for i in predList if ((i-predicted0)*100)/predicted0 < threshold]
|
||||
|
||||
return (len(over)/(len(over) + len(less)))
|
||||
|
||||
|
||||
def monte_carlo_simulation(simulated_returns: pd.Series, last_actual_price: float, n_days: int, plot=True):
|
||||
# Create empty matrix
|
||||
price_list = np.zeros_like(simulated_returns)
|
||||
|
||||
# Put the last actual price in the first row of matrix
|
||||
price_list[0] = last_actual_price
|
||||
|
||||
# Calculate the price of each day
|
||||
for t in range(1, n_days):
|
||||
price_list[t] = price_list[t-1]*simulated_returns[t]
|
||||
|
||||
# Plot
|
||||
if plot == True:
|
||||
x = pd.DataFrame(price_list).iloc[-1]
|
||||
fig, ax = plt.subplots(1, 2, figsize=(14,4))
|
||||
sns.distplot(x, ax=ax[0])
|
||||
sns.distplot(x, hist_kws={'cumulative': True}, kde_kws={'cumulative': True}, ax=ax[1])
|
||||
plt.xlabel('Stock Price')
|
||||
plt.show()
|
||||
|
||||
|
||||
print(f"Investment period: {n_days-1}")
|
||||
print(f"Expected Value: ${round(pd.DataFrame(price_list).iloc[-1].mean(),2)}")
|
||||
print(f"Return: {round(100*(pd.DataFrame(price_list).iloc[-1].mean()-price_list[0,1])/pd.DataFrame(price_list).iloc[-1].mean(),2)}%")
|
||||
print(f"Probability of Breakeven: {get_breakeven_prob(pd.DataFrame(price_list))}")
|
||||
|
||||
return pd.DataFrame(price_list)
|
||||
|
||||
|
||||
# %% Run Monte carlo simulation and estimate result
|
||||
|
||||
simulated_prices_df = monte_carlo_simulation(
|
||||
btcusd_simulated_returns,
|
||||
quotes_data[0]['close'].tail(1),
|
||||
n_days)
|
||||
|
||||
|
||||
plt.figure(figsize=(10,6))
|
||||
plt.plot(simulated_prices_df.iloc[:, 1:10])
|
||||
plt.show()
|
||||
|
||||
|
||||
|
||||
# %% Monte Carlo simulation pipeline for multiple tokens ----
|
||||
|
||||
n_iterations = int(1e4) #! WARN: set simulations number
|
||||
|
||||
returns_data = [get_returns(df['close']) for df in quotes_data]
|
||||
log_returns_data = [get_log_returns(r) for r in returns_data]
|
||||
simulated_returns_data = [get_simulated_returns(lr, n_days, n_iterations) for lr in log_returns_data]
|
||||
|
||||
|
||||
for i in range(len(simulated_returns_data)):
|
||||
print(f'Starting Monte-Carlo simulation for {symbols[i]} symbol...')
|
||||
prices_ms = monte_carlo_simulation(simulated_returns_data[i], quotes_data[i]['close'].tail(1), n_days, plot=True)
|
||||
|
||||
plt.figure(figsize=(10,6))
|
||||
plt.plot(prices_ms.iloc[:, 1:50])
|
||||
plt.show()
|
248
src/fx_currencies_analysis.Rmd
Executable file
248
src/fx_currencies_analysis.Rmd
Executable file
@ -0,0 +1,248 @@
|
||||
---
|
||||
title: "Currencies Analysis"
|
||||
date: "`r format(Sys.time(), '%d %B, %Y')`"
|
||||
output:
|
||||
github_document:
|
||||
toc: false
|
||||
toc_depth: 2
|
||||
fig_width: 9
|
||||
fig_height: 9
|
||||
---
|
||||
|
||||
```{r setup, include=FALSE}
|
||||
knitr::opts_chunk$set(echo = T, warning = F)
|
||||
```
|
||||
|
||||
***Analysis price of the my list of currencies.***
|
||||
|
||||
## Prepare
|
||||
|
||||
Install packages and set environment :earth_asia:
|
||||
|
||||
`install.packages("azuremlsdk")`
|
||||
|
||||
```{r set_envinroment, message=FALSE}
|
||||
options(max.print = 1e3, scipen = 999, width = 1e2)
|
||||
options(stringsAsFactors = F)
|
||||
|
||||
suppressPackageStartupMessages({
|
||||
library(dplyr)
|
||||
library(tidyr)
|
||||
|
||||
library(lubridate)
|
||||
library(stringr)
|
||||
|
||||
library(gt)
|
||||
library(tidyverse)
|
||||
library(glue)
|
||||
|
||||
library(ggplot2)
|
||||
|
||||
library(azuremlsdk)
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
```{r set_params}
|
||||
.azureml_dataset_name <- "Currencies"
|
||||
```
|
||||
|
||||
|
||||
Connect to Azure ML workspace:
|
||||
|
||||
```{r azureml_connect}
|
||||
ws <- azuremlsdk::load_workspace_from_config()
|
||||
sprintf(
|
||||
"%s workspace located in %s region", ws$name, ws$location
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
## Load dataset
|
||||
|
||||
WARNING: I used `currency exchange rates` data from [Kaggle Dataset](https://www.kaggle.com/datasets/dhruvildave/currency-exchange-rates):
|
||||
|
||||
```{r get_azure_dataset}
|
||||
currencies_ds <- azuremlsdk::get_dataset_by_name(ws, name = .azureml_dataset_name)
|
||||
|
||||
sprintf(
|
||||
"Dataset name: %s. %s",
|
||||
currencies_ds$name,
|
||||
currencies_ds$description
|
||||
)
|
||||
```
|
||||
|
||||
Get `USD/RUB` top higher rates:
|
||||
|
||||
```{r prepare_dataframe}
|
||||
quotes_df <- currencies_ds$to_pandas_dataframe()
|
||||
|
||||
# ~ 20 years, 150 currencies and 1.5M rows
|
||||
|
||||
quotes_df %>%
|
||||
filter(slug == "USD/RUB") %>%
|
||||
select(-slug) %>%
|
||||
top_n(10) %>%
|
||||
|
||||
gt() %>%
|
||||
tab_header(
|
||||
title = "USD/RUB Rate",
|
||||
subtitle = glue("{min(quotes_df$date)} to {max(quotes_df$date)}")
|
||||
) %>%
|
||||
fmt_date(
|
||||
columns = date,
|
||||
date_style = 6
|
||||
) %>%
|
||||
fmt_number(
|
||||
columns = c(open, high, low, close)
|
||||
)
|
||||
```
|
||||
|
||||
## Preprocessing data
|
||||
|
||||
Calculate `Return` and `Log Return` for last 10 years:
|
||||
|
||||
```{r preprocessing}
|
||||
quotes_df %<>%
|
||||
transmute(
|
||||
symbol = slug,
|
||||
price = close,
|
||||
date
|
||||
) %>%
|
||||
|
||||
filter(
|
||||
str_detect(symbol, "USD/") &
|
||||
date > max(date) - lubridate::years(10)
|
||||
) %>%
|
||||
|
||||
filter(!(symbol == "USD/RUB" & price < 1)) %>%
|
||||
|
||||
arrange(date) %>%
|
||||
group_by(symbol) %>%
|
||||
|
||||
mutate(
|
||||
return = c(NA_real_, diff(price))/lag(price),
|
||||
log_return = log(1 + return)
|
||||
) %>%
|
||||
na.omit
|
||||
```
|
||||
|
||||
## Discover Data
|
||||
|
||||
Calculate statistics and `volatility`:
|
||||
|
||||
```{r discover}
|
||||
quotes_stats <- quotes_df %>%
|
||||
|
||||
summarise(
|
||||
max_price = max(price),
|
||||
min_price = min(price),
|
||||
last_price = last(price),
|
||||
max_min_rate = max(price)/min(price),
|
||||
volatility = sd(log_return)
|
||||
)
|
||||
|
||||
quotes_stats %>%
|
||||
mutate(
|
||||
`100x Volatility` = volatility*100
|
||||
) %>%
|
||||
arrange(volatility) %>%
|
||||
select(-volatility) %>%
|
||||
|
||||
gt() %>%
|
||||
tab_header(
|
||||
title = "The Least and The Most Volatile Currencies",
|
||||
subtitle = glue("{min(quotes_df$date)} to {max(quotes_df$date)}")
|
||||
) %>%
|
||||
fmt_number(
|
||||
columns = c(max_price, min_price, max_min_rate, last_price, `100x Volatility`)
|
||||
)
|
||||
```
|
||||
My broker trades the following pairs:
|
||||
|
||||
```{r}
|
||||
symbols <- c(
|
||||
'RUB',
|
||||
'EUR', 'GBP', 'CHF', 'CNY', 'HKD', 'JPY', 'SEK', 'SGD', 'AUD',
|
||||
'AED', 'KZT', 'BYN', 'TRY', 'MXN'
|
||||
)
|
||||
|
||||
symbols <- str_c("USD", symbols, sep = "/")
|
||||
|
||||
|
||||
quotes_stats %>%
|
||||
filter(
|
||||
symbol %in% symbols
|
||||
) %>%
|
||||
mutate(
|
||||
`100x Volatility` = volatility*100
|
||||
) %>%
|
||||
arrange(volatility) %>%
|
||||
select(-volatility) %>%
|
||||
|
||||
gt() %>%
|
||||
tab_header(
|
||||
title = "The Most Promised Currencies",
|
||||
subtitle = glue("{min(quotes_df$date)} to {max(quotes_df$date)}")
|
||||
) %>%
|
||||
fmt_number(
|
||||
columns = c(max_price, min_price, last_price, max_min_rate, `100x Volatility`)
|
||||
)
|
||||
|
||||
```
|
||||
Plot exchange rate for out favorites:
|
||||
|
||||
Define low risk symbols:
|
||||
|
||||
```{r}
|
||||
usdrub_vol <- quotes_stats %>% filter(symbol == "USD/RUB") %>% pull(volatility)
|
||||
|
||||
low_risk_symbols <- quotes_stats %>%
|
||||
filter(
|
||||
symbol %in% symbols &
|
||||
volatility <= usdrub_vol
|
||||
) %>%
|
||||
pull(symbol) %>%
|
||||
unique
|
||||
|
||||
cat(
|
||||
sprintf(
|
||||
"['%s']",
|
||||
paste(low_risk_symbols, collapse = "', '")
|
||||
))
|
||||
```
|
||||
|
||||
|
||||
```{r}
|
||||
jumper_symbols <- quotes_stats %>% filter(max_min_rate > 2) %>% pull(symbol)
|
||||
|
||||
quotes_df %>%
|
||||
filter(symbol %in% low_risk_symbols) %>%
|
||||
mutate(
|
||||
jumper = if_else(symbol %in% jumper_symbols, "High risk currencies", "Low risk currencies")
|
||||
) %>%
|
||||
group_by(symbol) %>%
|
||||
mutate(R = cumsum(return)) %>%
|
||||
|
||||
ggplot +
|
||||
geom_line(aes(x = date, y = R, color = symbol)) +
|
||||
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
|
||||
|
||||
facet_grid(jumper ~ ., scales = "free") +
|
||||
|
||||
labs(
|
||||
title = "Currencies Exchange Rates", subtitle = "Return of Investment for last 10 years",
|
||||
x = "", y = "Return of Investment",
|
||||
caption = currencies_ds$description) +
|
||||
theme_minimal() +
|
||||
|
||||
theme(
|
||||
legend.position = "top", legend.title = element_blank(),
|
||||
plot.caption = element_text(size = 8)
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
947
src/fx_currencies_analysis.md
Normal file
947
src/fx_currencies_analysis.md
Normal file
@ -0,0 +1,947 @@
|
||||
Currencies Analysis
|
||||
================
|
||||
04 April, 2022
|
||||
|
||||
***Analysis price of the my list of currencies.***
|
||||
|
||||
## Prepare
|
||||
|
||||
Install packages and set environment :earth asia:
|
||||
|
||||
`install.packages("azuremlsdk")`
|
||||
|
||||
``` r
|
||||
options(max.print = 1e3, scipen = 999, width = 1e2)
|
||||
options(stringsAsFactors = F)
|
||||
|
||||
suppressPackageStartupMessages({
|
||||
library(dplyr)
|
||||
library(tidyr)
|
||||
|
||||
library(lubridate)
|
||||
library(stringr)
|
||||
|
||||
library(gt)
|
||||
library(tidyverse)
|
||||
library(glue)
|
||||
|
||||
library(ggplot2)
|
||||
|
||||
library(azuremlsdk)
|
||||
})
|
||||
```
|
||||
|
||||
``` r
|
||||
.azureml_dataset_name <- "Currencies"
|
||||
```
|
||||
|
||||
Connect to Azure ML workspace:
|
||||
|
||||
``` r
|
||||
ws <- azuremlsdk::load_workspace_from_config()
|
||||
sprintf(
|
||||
"%s workspace located in %s region", ws$name, ws$location
|
||||
)
|
||||
```
|
||||
|
||||
## [1] "portf-opt-ws workspace located in westeurope region"
|
||||
|
||||
## Load dataset
|
||||
|
||||
WARNING: I used `currency exchange rates` data from [Kaggle
|
||||
Dataset](https://www.kaggle.com/datasets/dhruvildave/currency-exchange-rates):
|
||||
|
||||
``` r
|
||||
currencies_ds <- azuremlsdk::get_dataset_by_name(ws, name = .azureml_dataset_name)
|
||||
|
||||
sprintf(
|
||||
"Dataset name: %s. %s",
|
||||
currencies_ds$name,
|
||||
currencies_ds$description
|
||||
)
|
||||
```
|
||||
|
||||
## [1] "Dataset name: Currencies. Source: https://www.kaggle.com/datasets/dhruvildave/currency-exchange-rates"
|
||||
|
||||
Get `USD/RUB` top higher rates:
|
||||
|
||||
``` r
|
||||
quotes_df <- currencies_ds$to_pandas_dataframe()
|
||||
|
||||
# ~ 20 years, 150 currencies and 1.5M rows
|
||||
|
||||
quotes_df %>%
|
||||
filter(slug == "USD/RUB") %>%
|
||||
select(-slug) %>%
|
||||
top_n(10) %>%
|
||||
|
||||
gt() %>%
|
||||
tab_header(
|
||||
title = "USD/RUB Rate",
|
||||
subtitle = glue("{min(quotes_df$date)} to {max(quotes_df$date)}")
|
||||
) %>%
|
||||
fmt_date(
|
||||
columns = date,
|
||||
date_style = 6
|
||||
) %>%
|
||||
fmt_number(
|
||||
columns = c(open, high, low, close)
|
||||
)
|
||||
```
|
||||
|
||||
## Selecting by close
|
||||
|
||||
|
||||
<table class="gt_table">
|
||||
<thead class="gt_header">
|
||||
<tr>
|
||||
<th colspan="5" class="gt_heading gt_title gt_font_normal" style>USD/RUB Rate</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="5" class="gt_heading gt_subtitle gt_font_normal gt_bottom_border" style>1996-10-30 to 2021-08-30</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<thead class="gt_col_headings">
|
||||
<tr>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_left" rowspan="1" colspan="1">date</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">open</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">high</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">low</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">close</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="gt_table_body">
|
||||
<tr><td class="gt_row gt_left">Jan 21, 2016</td>
|
||||
<td class="gt_row gt_right">82.06</td>
|
||||
<td class="gt_row gt_right">85.82</td>
|
||||
<td class="gt_row gt_right">82.06</td>
|
||||
<td class="gt_row gt_right">81.82</td></tr>
|
||||
<tr><td class="gt_row gt_left">Jan 22, 2016</td>
|
||||
<td class="gt_row gt_right">80.61</td>
|
||||
<td class="gt_row gt_right">81.26</td>
|
||||
<td class="gt_row gt_right">77.94</td>
|
||||
<td class="gt_row gt_right">82.90</td></tr>
|
||||
<tr><td class="gt_row gt_left">Jan 26, 2016</td>
|
||||
<td class="gt_row gt_right">81.54</td>
|
||||
<td class="gt_row gt_right">82.16</td>
|
||||
<td class="gt_row gt_right">78.33</td>
|
||||
<td class="gt_row gt_right">79.84</td></tr>
|
||||
<tr><td class="gt_row gt_left">Feb 3, 2016</td>
|
||||
<td class="gt_row gt_right">79.56</td>
|
||||
<td class="gt_row gt_right">79.75</td>
|
||||
<td class="gt_row gt_right">77.87</td>
|
||||
<td class="gt_row gt_right">79.71</td></tr>
|
||||
<tr><td class="gt_row gt_left">Feb 10, 2016</td>
|
||||
<td class="gt_row gt_right">79.39</td>
|
||||
<td class="gt_row gt_right">79.49</td>
|
||||
<td class="gt_row gt_right">77.65</td>
|
||||
<td class="gt_row gt_right">79.59</td></tr>
|
||||
<tr><td class="gt_row gt_left">Feb 12, 2016</td>
|
||||
<td class="gt_row gt_right">79.36</td>
|
||||
<td class="gt_row gt_right">79.74</td>
|
||||
<td class="gt_row gt_right">78.59</td>
|
||||
<td class="gt_row gt_right">79.77</td></tr>
|
||||
<tr><td class="gt_row gt_left">Mar 19, 2020</td>
|
||||
<td class="gt_row gt_right">80.92</td>
|
||||
<td class="gt_row gt_right">82.07</td>
|
||||
<td class="gt_row gt_right">79.24</td>
|
||||
<td class="gt_row gt_right">80.92</td></tr>
|
||||
<tr><td class="gt_row gt_left">Mar 23, 2020</td>
|
||||
<td class="gt_row gt_right">79.72</td>
|
||||
<td class="gt_row gt_right">81.34</td>
|
||||
<td class="gt_row gt_right">79.49</td>
|
||||
<td class="gt_row gt_right">79.84</td></tr>
|
||||
<tr><td class="gt_row gt_left">Mar 31, 2020</td>
|
||||
<td class="gt_row gt_right">79.59</td>
|
||||
<td class="gt_row gt_right">79.69</td>
|
||||
<td class="gt_row gt_right">77.66</td>
|
||||
<td class="gt_row gt_right">79.59</td></tr>
|
||||
<tr><td class="gt_row gt_left">Nov 3, 2020</td>
|
||||
<td class="gt_row gt_right">80.55</td>
|
||||
<td class="gt_row gt_right">80.57</td>
|
||||
<td class="gt_row gt_right">79.05</td>
|
||||
<td class="gt_row gt_right">80.52</td></tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
## Preprocessing data
|
||||
|
||||
Calculate `Return` and `Log Return` for last 10 years:
|
||||
|
||||
``` r
|
||||
quotes_df %<>%
|
||||
transmute(
|
||||
symbol = slug,
|
||||
price = close,
|
||||
date
|
||||
) %>%
|
||||
|
||||
filter(
|
||||
str_detect(symbol, "USD/") &
|
||||
date > max(date) - lubridate::years(10)
|
||||
) %>%
|
||||
|
||||
filter(!(symbol == "USD/RUB" & price < 1)) %>%
|
||||
|
||||
arrange(date) %>%
|
||||
group_by(symbol) %>%
|
||||
|
||||
mutate(
|
||||
return = c(NA_real_, diff(price))/lag(price),
|
||||
log_return = log(1 + return)
|
||||
) %>%
|
||||
na.omit
|
||||
```
|
||||
|
||||
## Discover Data
|
||||
|
||||
Calculate statistics and `volatility`:
|
||||
|
||||
``` r
|
||||
quotes_stats <- quotes_df %>%
|
||||
|
||||
summarise(
|
||||
max_price = max(price),
|
||||
min_price = min(price),
|
||||
last_price = last(price),
|
||||
max_min_rate = max(price)/min(price),
|
||||
volatility = sd(log_return)
|
||||
)
|
||||
|
||||
quotes_stats %>%
|
||||
mutate(
|
||||
`100x Volatility` = volatility*100
|
||||
) %>%
|
||||
arrange(volatility) %>%
|
||||
select(-volatility) %>%
|
||||
|
||||
gt() %>%
|
||||
tab_header(
|
||||
title = "The Least and The Most Volatile Currencies",
|
||||
subtitle = glue("{min(quotes_df$date)} to {max(quotes_df$date)}")
|
||||
) %>%
|
||||
fmt_number(
|
||||
columns = c(max_price, min_price, max_min_rate, last_price, `100x Volatility`)
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
<table class="gt_table">
|
||||
<thead class="gt_header">
|
||||
<tr>
|
||||
<th colspan="6" class="gt_heading gt_title gt_font_normal" style>The Least and The Most Volatile Currencies</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="6" class="gt_heading gt_subtitle gt_font_normal gt_bottom_border" style>2011-09-01 to 2021-08-30</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<thead class="gt_col_headings">
|
||||
<tr>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_left" rowspan="1" colspan="1">symbol</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">max_price</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">min_price</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">last_price</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">max_min_rate</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">100x Volatility</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="gt_table_body">
|
||||
<tr><td class="gt_row gt_left">USD/AED</td>
|
||||
<td class="gt_row gt_right">3.67</td>
|
||||
<td class="gt_row gt_right">3.67</td>
|
||||
<td class="gt_row gt_right">3.67</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">0.01</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/HKD</td>
|
||||
<td class="gt_row gt_right">7.85</td>
|
||||
<td class="gt_row gt_right">7.75</td>
|
||||
<td class="gt_row gt_right">7.79</td>
|
||||
<td class="gt_row gt_right">1.01</td>
|
||||
<td class="gt_row gt_right">0.03</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/KWD</td>
|
||||
<td class="gt_row gt_right">0.31</td>
|
||||
<td class="gt_row gt_right">0.27</td>
|
||||
<td class="gt_row gt_right">0.30</td>
|
||||
<td class="gt_row gt_right">1.16</td>
|
||||
<td class="gt_row gt_right">0.16</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CNY</td>
|
||||
<td class="gt_row gt_right">7.18</td>
|
||||
<td class="gt_row gt_right">6.03</td>
|
||||
<td class="gt_row gt_right">6.47</td>
|
||||
<td class="gt_row gt_right">1.19</td>
|
||||
<td class="gt_row gt_right">0.23</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/DJF</td>
|
||||
<td class="gt_row gt_right">177.72</td>
|
||||
<td class="gt_row gt_right">172.00</td>
|
||||
<td class="gt_row gt_right">177.50</td>
|
||||
<td class="gt_row gt_right">1.03</td>
|
||||
<td class="gt_row gt_right">0.28</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SGD</td>
|
||||
<td class="gt_row gt_right">1.46</td>
|
||||
<td class="gt_row gt_right">1.20</td>
|
||||
<td class="gt_row gt_right">1.34</td>
|
||||
<td class="gt_row gt_right">1.21</td>
|
||||
<td class="gt_row gt_right">0.33</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SAR</td>
|
||||
<td class="gt_row gt_right">3.77</td>
|
||||
<td class="gt_row gt_right">3.30</td>
|
||||
<td class="gt_row gt_right">3.75</td>
|
||||
<td class="gt_row gt_right">1.14</td>
|
||||
<td class="gt_row gt_right">0.39</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/GTQ</td>
|
||||
<td class="gt_row gt_right">7.89</td>
|
||||
<td class="gt_row gt_right">7.04</td>
|
||||
<td class="gt_row gt_right">7.73</td>
|
||||
<td class="gt_row gt_right">1.12</td>
|
||||
<td class="gt_row gt_right">0.41</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/ILS</td>
|
||||
<td class="gt_row gt_right">4.07</td>
|
||||
<td class="gt_row gt_right">3.13</td>
|
||||
<td class="gt_row gt_right">3.20</td>
|
||||
<td class="gt_row gt_right">1.30</td>
|
||||
<td class="gt_row gt_right">0.45</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/TTD</td>
|
||||
<td class="gt_row gt_right">6.78</td>
|
||||
<td class="gt_row gt_right">5.93</td>
|
||||
<td class="gt_row gt_right">6.76</td>
|
||||
<td class="gt_row gt_right">1.14</td>
|
||||
<td class="gt_row gt_right">0.47</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CAD</td>
|
||||
<td class="gt_row gt_right">1.46</td>
|
||||
<td class="gt_row gt_right">0.97</td>
|
||||
<td class="gt_row gt_right">1.26</td>
|
||||
<td class="gt_row gt_right">1.51</td>
|
||||
<td class="gt_row gt_right">0.47</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MYR</td>
|
||||
<td class="gt_row gt_right">4.49</td>
|
||||
<td class="gt_row gt_right">2.96</td>
|
||||
<td class="gt_row gt_right">4.16</td>
|
||||
<td class="gt_row gt_right">1.52</td>
|
||||
<td class="gt_row gt_right">0.50</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/DKK</td>
|
||||
<td class="gt_row gt_right">7.15</td>
|
||||
<td class="gt_row gt_right">5.18</td>
|
||||
<td class="gt_row gt_right">6.30</td>
|
||||
<td class="gt_row gt_right">1.38</td>
|
||||
<td class="gt_row gt_right">0.51</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/EUR</td>
|
||||
<td class="gt_row gt_right">0.96</td>
|
||||
<td class="gt_row gt_right">0.70</td>
|
||||
<td class="gt_row gt_right">0.85</td>
|
||||
<td class="gt_row gt_right">1.38</td>
|
||||
<td class="gt_row gt_right">0.51</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CRC</td>
|
||||
<td class="gt_row gt_right">619.70</td>
|
||||
<td class="gt_row gt_right">478.54</td>
|
||||
<td class="gt_row gt_right">619.70</td>
|
||||
<td class="gt_row gt_right">1.29</td>
|
||||
<td class="gt_row gt_right">0.53</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/PHP</td>
|
||||
<td class="gt_row gt_right">54.23</td>
|
||||
<td class="gt_row gt_right">39.75</td>
|
||||
<td class="gt_row gt_right">49.71</td>
|
||||
<td class="gt_row gt_right">1.36</td>
|
||||
<td class="gt_row gt_right">0.54</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/INR</td>
|
||||
<td class="gt_row gt_right">77.57</td>
|
||||
<td class="gt_row gt_right">45.70</td>
|
||||
<td class="gt_row gt_right">73.29</td>
|
||||
<td class="gt_row gt_right">1.70</td>
|
||||
<td class="gt_row gt_right">0.54</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/RON</td>
|
||||
<td class="gt_row gt_right">4.54</td>
|
||||
<td class="gt_row gt_right">2.93</td>
|
||||
<td class="gt_row gt_right">4.18</td>
|
||||
<td class="gt_row gt_right">1.55</td>
|
||||
<td class="gt_row gt_right">0.55</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/JPY</td>
|
||||
<td class="gt_row gt_right">125.63</td>
|
||||
<td class="gt_row gt_right">75.74</td>
|
||||
<td class="gt_row gt_right">109.90</td>
|
||||
<td class="gt_row gt_right">1.66</td>
|
||||
<td class="gt_row gt_right">0.55</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/GBP</td>
|
||||
<td class="gt_row gt_right">0.87</td>
|
||||
<td class="gt_row gt_right">0.58</td>
|
||||
<td class="gt_row gt_right">0.73</td>
|
||||
<td class="gt_row gt_right">1.49</td>
|
||||
<td class="gt_row gt_right">0.55</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/JMD</td>
|
||||
<td class="gt_row gt_right">153.88</td>
|
||||
<td class="gt_row gt_right">83.37</td>
|
||||
<td class="gt_row gt_right">150.53</td>
|
||||
<td class="gt_row gt_right">1.85</td>
|
||||
<td class="gt_row gt_right">0.56</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MKD</td>
|
||||
<td class="gt_row gt_right">58.92</td>
|
||||
<td class="gt_row gt_right">42.07</td>
|
||||
<td class="gt_row gt_right">51.98</td>
|
||||
<td class="gt_row gt_right">1.40</td>
|
||||
<td class="gt_row gt_right">0.58</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MDL</td>
|
||||
<td class="gt_row gt_right">20.31</td>
|
||||
<td class="gt_row gt_right">11.09</td>
|
||||
<td class="gt_row gt_right">17.58</td>
|
||||
<td class="gt_row gt_right">1.83</td>
|
||||
<td class="gt_row gt_right">0.61</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/BDT</td>
|
||||
<td class="gt_row gt_right">84.72</td>
|
||||
<td class="gt_row gt_right">72.39</td>
|
||||
<td class="gt_row gt_right">84.72</td>
|
||||
<td class="gt_row gt_right">1.17</td>
|
||||
<td class="gt_row gt_right">0.62</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/AUD</td>
|
||||
<td class="gt_row gt_right">1.74</td>
|
||||
<td class="gt_row gt_right">0.93</td>
|
||||
<td class="gt_row gt_right">1.37</td>
|
||||
<td class="gt_row gt_right">1.88</td>
|
||||
<td class="gt_row gt_right">0.63</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SEK</td>
|
||||
<td class="gt_row gt_right">10.44</td>
|
||||
<td class="gt_row gt_right">6.29</td>
|
||||
<td class="gt_row gt_right">8.62</td>
|
||||
<td class="gt_row gt_right">1.66</td>
|
||||
<td class="gt_row gt_right">0.64</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CHF</td>
|
||||
<td class="gt_row gt_right">1.03</td>
|
||||
<td class="gt_row gt_right">0.79</td>
|
||||
<td class="gt_row gt_right">0.92</td>
|
||||
<td class="gt_row gt_right">1.31</td>
|
||||
<td class="gt_row gt_right">0.64</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CZK</td>
|
||||
<td class="gt_row gt_right">26.03</td>
|
||||
<td class="gt_row gt_right">16.75</td>
|
||||
<td class="gt_row gt_right">21.67</td>
|
||||
<td class="gt_row gt_right">1.55</td>
|
||||
<td class="gt_row gt_right">0.64</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/BWP</td>
|
||||
<td class="gt_row gt_right">12.19</td>
|
||||
<td class="gt_row gt_right">6.58</td>
|
||||
<td class="gt_row gt_right">11.12</td>
|
||||
<td class="gt_row gt_right">1.85</td>
|
||||
<td class="gt_row gt_right">0.66</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/NZD</td>
|
||||
<td class="gt_row gt_right">1.78</td>
|
||||
<td class="gt_row gt_right">1.13</td>
|
||||
<td class="gt_row gt_right">1.43</td>
|
||||
<td class="gt_row gt_right">1.57</td>
|
||||
<td class="gt_row gt_right">0.66</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/THB</td>
|
||||
<td class="gt_row gt_right">36.43</td>
|
||||
<td class="gt_row gt_right">28.07</td>
|
||||
<td class="gt_row gt_right">32.45</td>
|
||||
<td class="gt_row gt_right">1.30</td>
|
||||
<td class="gt_row gt_right">0.67</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/LKR</td>
|
||||
<td class="gt_row gt_right">199.43</td>
|
||||
<td class="gt_row gt_right">106.22</td>
|
||||
<td class="gt_row gt_right">199.43</td>
|
||||
<td class="gt_row gt_right">1.88</td>
|
||||
<td class="gt_row gt_right">0.67</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/KRW</td>
|
||||
<td class="gt_row gt_right">1,262.93</td>
|
||||
<td class="gt_row gt_right">999.83</td>
|
||||
<td class="gt_row gt_right">1,165.89</td>
|
||||
<td class="gt_row gt_right">1.26</td>
|
||||
<td class="gt_row gt_right">0.70</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/RSD</td>
|
||||
<td class="gt_row gt_right">118.47</td>
|
||||
<td class="gt_row gt_right">70.05</td>
|
||||
<td class="gt_row gt_right">99.29</td>
|
||||
<td class="gt_row gt_right">1.69</td>
|
||||
<td class="gt_row gt_right">0.70</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/UYU</td>
|
||||
<td class="gt_row gt_right">45.31</td>
|
||||
<td class="gt_row gt_right">18.08</td>
|
||||
<td class="gt_row gt_right">42.53</td>
|
||||
<td class="gt_row gt_right">2.51</td>
|
||||
<td class="gt_row gt_right">0.71</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/PLN</td>
|
||||
<td class="gt_row gt_right">4.28</td>
|
||||
<td class="gt_row gt_right">2.87</td>
|
||||
<td class="gt_row gt_right">3.86</td>
|
||||
<td class="gt_row gt_right">1.49</td>
|
||||
<td class="gt_row gt_right">0.72</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/HUF</td>
|
||||
<td class="gt_row gt_right">338.26</td>
|
||||
<td class="gt_row gt_right">188.61</td>
|
||||
<td class="gt_row gt_right">294.66</td>
|
||||
<td class="gt_row gt_right">1.79</td>
|
||||
<td class="gt_row gt_right">0.74</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MUR</td>
|
||||
<td class="gt_row gt_right">42.55</td>
|
||||
<td class="gt_row gt_right">26.50</td>
|
||||
<td class="gt_row gt_right">42.55</td>
|
||||
<td class="gt_row gt_right">1.61</td>
|
||||
<td class="gt_row gt_right">0.79</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MXN</td>
|
||||
<td class="gt_row gt_right">25.34</td>
|
||||
<td class="gt_row gt_right">11.98</td>
|
||||
<td class="gt_row gt_right">20.14</td>
|
||||
<td class="gt_row gt_right">2.11</td>
|
||||
<td class="gt_row gt_right">0.80</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/NIO</td>
|
||||
<td class="gt_row gt_right">35.13</td>
|
||||
<td class="gt_row gt_right">22.05</td>
|
||||
<td class="gt_row gt_right">35.00</td>
|
||||
<td class="gt_row gt_right">1.59</td>
|
||||
<td class="gt_row gt_right">0.84</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/KZT</td>
|
||||
<td class="gt_row gt_right">454.34</td>
|
||||
<td class="gt_row gt_right">174.15</td>
|
||||
<td class="gt_row gt_right">427.18</td>
|
||||
<td class="gt_row gt_right">2.61</td>
|
||||
<td class="gt_row gt_right">0.84</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/QAR</td>
|
||||
<td class="gt_row gt_right">3.90</td>
|
||||
<td class="gt_row gt_right">3.00</td>
|
||||
<td class="gt_row gt_right">3.64</td>
|
||||
<td class="gt_row gt_right">1.30</td>
|
||||
<td class="gt_row gt_right">0.95</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/TRY</td>
|
||||
<td class="gt_row gt_right">8.78</td>
|
||||
<td class="gt_row gt_right">1.71</td>
|
||||
<td class="gt_row gt_right">8.38</td>
|
||||
<td class="gt_row gt_right">5.12</td>
|
||||
<td class="gt_row gt_right">0.97</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/ZAR</td>
|
||||
<td class="gt_row gt_right">19.25</td>
|
||||
<td class="gt_row gt_right">6.98</td>
|
||||
<td class="gt_row gt_right">14.66</td>
|
||||
<td class="gt_row gt_right">2.76</td>
|
||||
<td class="gt_row gt_right">0.99</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/RUB</td>
|
||||
<td class="gt_row gt_right">82.90</td>
|
||||
<td class="gt_row gt_right">28.79</td>
|
||||
<td class="gt_row gt_right">73.50</td>
|
||||
<td class="gt_row gt_right">2.88</td>
|
||||
<td class="gt_row gt_right">1.05</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/ZMW</td>
|
||||
<td class="gt_row gt_right">22.64</td>
|
||||
<td class="gt_row gt_right">5.11</td>
|
||||
<td class="gt_row gt_right">15.82</td>
|
||||
<td class="gt_row gt_right">4.43</td>
|
||||
<td class="gt_row gt_right">1.06</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/BRL</td>
|
||||
<td class="gt_row gt_right">5.89</td>
|
||||
<td class="gt_row gt_right">1.58</td>
|
||||
<td class="gt_row gt_right">5.19</td>
|
||||
<td class="gt_row gt_right">3.72</td>
|
||||
<td class="gt_row gt_right">1.08</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/ARS</td>
|
||||
<td class="gt_row gt_right">97.70</td>
|
||||
<td class="gt_row gt_right">4.10</td>
|
||||
<td class="gt_row gt_right">97.70</td>
|
||||
<td class="gt_row gt_right">23.85</td>
|
||||
<td class="gt_row gt_right">1.11</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/TND</td>
|
||||
<td class="gt_row gt_right">3.06</td>
|
||||
<td class="gt_row gt_right">1.37</td>
|
||||
<td class="gt_row gt_right">2.79</td>
|
||||
<td class="gt_row gt_right">2.23</td>
|
||||
<td class="gt_row gt_right">1.17</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/BGN</td>
|
||||
<td class="gt_row gt_right">1.87</td>
|
||||
<td class="gt_row gt_right">1.21</td>
|
||||
<td class="gt_row gt_right">1.66</td>
|
||||
<td class="gt_row gt_right">1.55</td>
|
||||
<td class="gt_row gt_right">1.28</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/EGP</td>
|
||||
<td class="gt_row gt_right">19.60</td>
|
||||
<td class="gt_row gt_right">5.83</td>
|
||||
<td class="gt_row gt_right">15.65</td>
|
||||
<td class="gt_row gt_right">3.37</td>
|
||||
<td class="gt_row gt_right">1.29</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/NOK</td>
|
||||
<td class="gt_row gt_right">11.76</td>
|
||||
<td class="gt_row gt_right">5.36</td>
|
||||
<td class="gt_row gt_right">8.66</td>
|
||||
<td class="gt_row gt_right">2.19</td>
|
||||
<td class="gt_row gt_right">1.31</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/PEN</td>
|
||||
<td class="gt_row gt_right">4.11</td>
|
||||
<td class="gt_row gt_right">2.38</td>
|
||||
<td class="gt_row gt_right">4.07</td>
|
||||
<td class="gt_row gt_right">1.72</td>
|
||||
<td class="gt_row gt_right">1.34</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/BYN</td>
|
||||
<td class="gt_row gt_right">3.08</td>
|
||||
<td class="gt_row gt_right">0.51</td>
|
||||
<td class="gt_row gt_right">2.51</td>
|
||||
<td class="gt_row gt_right">6.04</td>
|
||||
<td class="gt_row gt_right">1.37</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MAD</td>
|
||||
<td class="gt_row gt_right">10.29</td>
|
||||
<td class="gt_row gt_right">7.89</td>
|
||||
<td class="gt_row gt_right">8.95</td>
|
||||
<td class="gt_row gt_right">1.30</td>
|
||||
<td class="gt_row gt_right">1.43</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/UAH</td>
|
||||
<td class="gt_row gt_right">33.50</td>
|
||||
<td class="gt_row gt_right">7.80</td>
|
||||
<td class="gt_row gt_right">26.92</td>
|
||||
<td class="gt_row gt_right">4.30</td>
|
||||
<td class="gt_row gt_right">1.83</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SDG</td>
|
||||
<td class="gt_row gt_right">451.00</td>
|
||||
<td class="gt_row gt_right">1.39</td>
|
||||
<td class="gt_row gt_right">440.03</td>
|
||||
<td class="gt_row gt_right">324.46</td>
|
||||
<td class="gt_row gt_right">5.96</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/BND</td>
|
||||
<td class="gt_row gt_right">1.43</td>
|
||||
<td class="gt_row gt_right">0.66</td>
|
||||
<td class="gt_row gt_right">1.34</td>
|
||||
<td class="gt_row gt_right">2.18</td>
|
||||
<td class="gt_row gt_right">6.29</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/XOF</td>
|
||||
<td class="gt_row gt_right">647.00</td>
|
||||
<td class="gt_row gt_right">58.00</td>
|
||||
<td class="gt_row gt_right">555.47</td>
|
||||
<td class="gt_row gt_right">11.16</td>
|
||||
<td class="gt_row gt_right">6.44</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/IDR</td>
|
||||
<td class="gt_row gt_right">16,504.80</td>
|
||||
<td class="gt_row gt_right">892.00</td>
|
||||
<td class="gt_row gt_right">14,370.00</td>
|
||||
<td class="gt_row gt_right">18.50</td>
|
||||
<td class="gt_row gt_right">6.58</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/HNL</td>
|
||||
<td class="gt_row gt_right">24.90</td>
|
||||
<td class="gt_row gt_right">3.00</td>
|
||||
<td class="gt_row gt_right">23.83</td>
|
||||
<td class="gt_row gt_right">8.30</td>
|
||||
<td class="gt_row gt_right">8.14</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MZN</td>
|
||||
<td class="gt_row gt_right">78.49</td>
|
||||
<td class="gt_row gt_right">3.30</td>
|
||||
<td class="gt_row gt_right">63.11</td>
|
||||
<td class="gt_row gt_right">23.78</td>
|
||||
<td class="gt_row gt_right">8.77</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/ETB</td>
|
||||
<td class="gt_row gt_right">45.23</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">45.06</td>
|
||||
<td class="gt_row gt_right">45.23</td>
|
||||
<td class="gt_row gt_right">9.26</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/TWD</td>
|
||||
<td class="gt_row gt_right">33.73</td>
|
||||
<td class="gt_row gt_right">1.80</td>
|
||||
<td class="gt_row gt_right">27.77</td>
|
||||
<td class="gt_row gt_right">18.72</td>
|
||||
<td class="gt_row gt_right">9.86</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/PKR</td>
|
||||
<td class="gt_row gt_right">168.15</td>
|
||||
<td class="gt_row gt_right">2.00</td>
|
||||
<td class="gt_row gt_right">165.63</td>
|
||||
<td class="gt_row gt_right">84.07</td>
|
||||
<td class="gt_row gt_right">12.69</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/UZS</td>
|
||||
<td class="gt_row gt_right">10,653.20</td>
|
||||
<td class="gt_row gt_right">83.00</td>
|
||||
<td class="gt_row gt_right">10,646.89</td>
|
||||
<td class="gt_row gt_right">128.35</td>
|
||||
<td class="gt_row gt_right">12.93</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/GHS</td>
|
||||
<td class="gt_row gt_right">573.00</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">5.98</td>
|
||||
<td class="gt_row gt_right">573.00</td>
|
||||
<td class="gt_row gt_right">13.74</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/ISK</td>
|
||||
<td class="gt_row gt_right">147.04</td>
|
||||
<td class="gt_row gt_right">2.00</td>
|
||||
<td class="gt_row gt_right">126.65</td>
|
||||
<td class="gt_row gt_right">73.52</td>
|
||||
<td class="gt_row gt_right">16.09</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/PGK</td>
|
||||
<td class="gt_row gt_right">3.51</td>
|
||||
<td class="gt_row gt_right">0.29</td>
|
||||
<td class="gt_row gt_right">3.51</td>
|
||||
<td class="gt_row gt_right">11.89</td>
|
||||
<td class="gt_row gt_right">16.18</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MMK</td>
|
||||
<td class="gt_row gt_right">1,642.00</td>
|
||||
<td class="gt_row gt_right">6.23</td>
|
||||
<td class="gt_row gt_right">1,642.00</td>
|
||||
<td class="gt_row gt_right">263.65</td>
|
||||
<td class="gt_row gt_right">16.59</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CLP</td>
|
||||
<td class="gt_row gt_right">867.50</td>
|
||||
<td class="gt_row gt_right">5.00</td>
|
||||
<td class="gt_row gt_right">782.21</td>
|
||||
<td class="gt_row gt_right">173.50</td>
|
||||
<td class="gt_row gt_right">18.70</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SZL</td>
|
||||
<td class="gt_row gt_right">1,189.00</td>
|
||||
<td class="gt_row gt_right">1.07</td>
|
||||
<td class="gt_row gt_right">14.91</td>
|
||||
<td class="gt_row gt_right">1,111.21</td>
|
||||
<td class="gt_row gt_right">18.79</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/XPF</td>
|
||||
<td class="gt_row gt_right">119.35</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">100.90</td>
|
||||
<td class="gt_row gt_right">119.35</td>
|
||||
<td class="gt_row gt_right">19.32</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SOS</td>
|
||||
<td class="gt_row gt_right">1,670.00</td>
|
||||
<td class="gt_row gt_right">6.00</td>
|
||||
<td class="gt_row gt_right">571.00</td>
|
||||
<td class="gt_row gt_right">278.33</td>
|
||||
<td class="gt_row gt_right">29.77</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MWK</td>
|
||||
<td class="gt_row gt_right">812.43</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">804.55</td>
|
||||
<td class="gt_row gt_right">812.43</td>
|
||||
<td class="gt_row gt_right">30.83</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/NGN</td>
|
||||
<td class="gt_row gt_right">412.50</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">411.00</td>
|
||||
<td class="gt_row gt_right">412.50</td>
|
||||
<td class="gt_row gt_right">31.65</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/VND</td>
|
||||
<td class="gt_row gt_right">23,631.00</td>
|
||||
<td class="gt_row gt_right">21.00</td>
|
||||
<td class="gt_row gt_right">22,775.00</td>
|
||||
<td class="gt_row gt_right">1,125.29</td>
|
||||
<td class="gt_row gt_right">34.09</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/COP</td>
|
||||
<td class="gt_row gt_right">4,174.75</td>
|
||||
<td class="gt_row gt_right">3.67</td>
|
||||
<td class="gt_row gt_right">3,805.25</td>
|
||||
<td class="gt_row gt_right">1,136.67</td>
|
||||
<td class="gt_row gt_right">37.09</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/IQD</td>
|
||||
<td class="gt_row gt_right">1,578.00</td>
|
||||
<td class="gt_row gt_right">10.00</td>
|
||||
<td class="gt_row gt_right">1,458.00</td>
|
||||
<td class="gt_row gt_right">157.80</td>
|
||||
<td class="gt_row gt_right">37.10</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MGA</td>
|
||||
<td class="gt_row gt_right">3,931.18</td>
|
||||
<td class="gt_row gt_right">0.30</td>
|
||||
<td class="gt_row gt_right">3,808.00</td>
|
||||
<td class="gt_row gt_right">12,910.29</td>
|
||||
<td class="gt_row gt_right">46.29</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SLL</td>
|
||||
<td class="gt_row gt_right">10,250.50</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">10,250.50</td>
|
||||
<td class="gt_row gt_right">10,250.50</td>
|
||||
<td class="gt_row gt_right">47.59</td></tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
My broker trades the following pairs:
|
||||
|
||||
``` r
|
||||
symbols <- c(
|
||||
'RUB',
|
||||
'EUR', 'GBP', 'CHF', 'CNY', 'HKD', 'JPY', 'SEK', 'SGD', 'AUD',
|
||||
'AED', 'KZT', 'BYN', 'TRY', 'MXN'
|
||||
)
|
||||
|
||||
symbols <- str_c("USD", symbols, sep = "/")
|
||||
|
||||
|
||||
quotes_stats %>%
|
||||
filter(
|
||||
symbol %in% symbols
|
||||
) %>%
|
||||
mutate(
|
||||
`100x Volatility` = volatility*100
|
||||
) %>%
|
||||
arrange(volatility) %>%
|
||||
select(-volatility) %>%
|
||||
|
||||
gt() %>%
|
||||
tab_header(
|
||||
title = "The Most Promised Currencies",
|
||||
subtitle = glue("{min(quotes_df$date)} to {max(quotes_df$date)}")
|
||||
) %>%
|
||||
fmt_number(
|
||||
columns = c(max_price, min_price, last_price, max_min_rate, `100x Volatility`)
|
||||
)
|
||||
```
|
||||
|
||||
<div id="arrslcwxgh" style="overflow-x:auto;overflow-y:auto;width:auto;height:auto;">
|
||||
|
||||
<table class="gt_table">
|
||||
<thead class="gt_header">
|
||||
<tr>
|
||||
<th colspan="6" class="gt_heading gt_title gt_font_normal" style>The Most Promised Currencies</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="6" class="gt_heading gt_subtitle gt_font_normal gt_bottom_border" style>2011-09-01 to 2021-08-30</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<thead class="gt_col_headings">
|
||||
<tr>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_left" rowspan="1" colspan="1">symbol</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">max_price</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">min_price</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">last_price</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">max_min_rate</th>
|
||||
<th class="gt_col_heading gt_columns_bottom_border gt_right" rowspan="1" colspan="1">100x Volatility</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="gt_table_body">
|
||||
<tr><td class="gt_row gt_left">USD/AED</td>
|
||||
<td class="gt_row gt_right">3.67</td>
|
||||
<td class="gt_row gt_right">3.67</td>
|
||||
<td class="gt_row gt_right">3.67</td>
|
||||
<td class="gt_row gt_right">1.00</td>
|
||||
<td class="gt_row gt_right">0.01</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/HKD</td>
|
||||
<td class="gt_row gt_right">7.85</td>
|
||||
<td class="gt_row gt_right">7.75</td>
|
||||
<td class="gt_row gt_right">7.79</td>
|
||||
<td class="gt_row gt_right">1.01</td>
|
||||
<td class="gt_row gt_right">0.03</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CNY</td>
|
||||
<td class="gt_row gt_right">7.18</td>
|
||||
<td class="gt_row gt_right">6.03</td>
|
||||
<td class="gt_row gt_right">6.47</td>
|
||||
<td class="gt_row gt_right">1.19</td>
|
||||
<td class="gt_row gt_right">0.23</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SGD</td>
|
||||
<td class="gt_row gt_right">1.46</td>
|
||||
<td class="gt_row gt_right">1.20</td>
|
||||
<td class="gt_row gt_right">1.34</td>
|
||||
<td class="gt_row gt_right">1.21</td>
|
||||
<td class="gt_row gt_right">0.33</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/EUR</td>
|
||||
<td class="gt_row gt_right">0.96</td>
|
||||
<td class="gt_row gt_right">0.70</td>
|
||||
<td class="gt_row gt_right">0.85</td>
|
||||
<td class="gt_row gt_right">1.38</td>
|
||||
<td class="gt_row gt_right">0.51</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/JPY</td>
|
||||
<td class="gt_row gt_right">125.63</td>
|
||||
<td class="gt_row gt_right">75.74</td>
|
||||
<td class="gt_row gt_right">109.90</td>
|
||||
<td class="gt_row gt_right">1.66</td>
|
||||
<td class="gt_row gt_right">0.55</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/GBP</td>
|
||||
<td class="gt_row gt_right">0.87</td>
|
||||
<td class="gt_row gt_right">0.58</td>
|
||||
<td class="gt_row gt_right">0.73</td>
|
||||
<td class="gt_row gt_right">1.49</td>
|
||||
<td class="gt_row gt_right">0.55</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/AUD</td>
|
||||
<td class="gt_row gt_right">1.74</td>
|
||||
<td class="gt_row gt_right">0.93</td>
|
||||
<td class="gt_row gt_right">1.37</td>
|
||||
<td class="gt_row gt_right">1.88</td>
|
||||
<td class="gt_row gt_right">0.63</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/SEK</td>
|
||||
<td class="gt_row gt_right">10.44</td>
|
||||
<td class="gt_row gt_right">6.29</td>
|
||||
<td class="gt_row gt_right">8.62</td>
|
||||
<td class="gt_row gt_right">1.66</td>
|
||||
<td class="gt_row gt_right">0.64</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/CHF</td>
|
||||
<td class="gt_row gt_right">1.03</td>
|
||||
<td class="gt_row gt_right">0.79</td>
|
||||
<td class="gt_row gt_right">0.92</td>
|
||||
<td class="gt_row gt_right">1.31</td>
|
||||
<td class="gt_row gt_right">0.64</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/MXN</td>
|
||||
<td class="gt_row gt_right">25.34</td>
|
||||
<td class="gt_row gt_right">11.98</td>
|
||||
<td class="gt_row gt_right">20.14</td>
|
||||
<td class="gt_row gt_right">2.11</td>
|
||||
<td class="gt_row gt_right">0.80</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/KZT</td>
|
||||
<td class="gt_row gt_right">454.34</td>
|
||||
<td class="gt_row gt_right">174.15</td>
|
||||
<td class="gt_row gt_right">427.18</td>
|
||||
<td class="gt_row gt_right">2.61</td>
|
||||
<td class="gt_row gt_right">0.84</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/TRY</td>
|
||||
<td class="gt_row gt_right">8.78</td>
|
||||
<td class="gt_row gt_right">1.71</td>
|
||||
<td class="gt_row gt_right">8.38</td>
|
||||
<td class="gt_row gt_right">5.12</td>
|
||||
<td class="gt_row gt_right">0.97</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/RUB</td>
|
||||
<td class="gt_row gt_right">82.90</td>
|
||||
<td class="gt_row gt_right">28.79</td>
|
||||
<td class="gt_row gt_right">73.50</td>
|
||||
<td class="gt_row gt_right">2.88</td>
|
||||
<td class="gt_row gt_right">1.05</td></tr>
|
||||
<tr><td class="gt_row gt_left">USD/BYN</td>
|
||||
<td class="gt_row gt_right">3.08</td>
|
||||
<td class="gt_row gt_right">0.51</td>
|
||||
<td class="gt_row gt_right">2.51</td>
|
||||
<td class="gt_row gt_right">6.04</td>
|
||||
<td class="gt_row gt_right">1.37</td></tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Plot exchange rate for out favorites:
|
||||
|
||||
Define low risk symbols:
|
||||
|
||||
``` r
|
||||
usdrub_vol <- quotes_stats %>% filter(symbol == "USD/RUB") %>% pull(volatility)
|
||||
|
||||
low_risk_symbols <- quotes_stats %>%
|
||||
filter(
|
||||
symbol %in% symbols &
|
||||
volatility <= usdrub_vol
|
||||
) %>%
|
||||
pull(symbol) %>%
|
||||
unique
|
||||
|
||||
cat(
|
||||
sprintf(
|
||||
"['%s']",
|
||||
paste(low_risk_symbols, collapse = "', '")
|
||||
))
|
||||
```
|
||||
|
||||
## ['USD/AED', 'USD/AUD', 'USD/CHF', 'USD/CNY', 'USD/EUR', 'USD/GBP', 'USD/HKD', 'USD/JPY', 'USD/KZT', 'USD/MXN', 'USD/RUB', 'USD/SEK', 'USD/SGD', 'USD/TRY']
|
||||
|
||||
``` r
|
||||
jumper_symbols <- quotes_stats %>% filter(max_min_rate > 2) %>% pull(symbol)
|
||||
|
||||
quotes_df %>%
|
||||
filter(symbol %in% low_risk_symbols) %>%
|
||||
mutate(
|
||||
jumper = if_else(symbol %in% jumper_symbols, "High risk currencies", "Low risk currencies")
|
||||
) %>%
|
||||
group_by(symbol) %>%
|
||||
mutate(R = cumsum(return)) %>%
|
||||
|
||||
ggplot +
|
||||
geom_line(aes(x = date, y = R, color = symbol)) +
|
||||
scale_y_continuous(labels = scales::percent_format(accuracy = 1)) +
|
||||
|
||||
facet_grid(jumper ~ ., scales = "free") +
|
||||
|
||||
labs(
|
||||
title = "Currencies Exchange Rates", subtitle = "Return of Investment for last 10 years",
|
||||
x = "", y = "Return of Investment",
|
||||
caption = currencies_ds$description) +
|
||||
theme_minimal() +
|
||||
|
||||
theme(
|
||||
legend.position = "top", legend.title = element_blank(),
|
||||
plot.caption = element_text(size = 8)
|
||||
)
|
||||
```
|
||||
|
||||
![](fx_currencies_analysis_files/figure-gfm/unnamed-chunk-3-1.png)<!-- -->
|
Binary file not shown.
After Width: | Height: | Size: 209 KiB |
1318
src/fx_currency_portfolio__assets_selection.ipynb
Normal file
1318
src/fx_currency_portfolio__assets_selection.ipynb
Normal file
File diff suppressed because one or more lines are too long
242
src/fx_currency_portfolio__assets_selection.py
Normal file
242
src/fx_currency_portfolio__assets_selection.py
Normal file
@ -0,0 +1,242 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
"""Currency Portfolio: Assets Selection.
|
||||
|
||||
Description:
|
||||
Currency Selection in anti-crisis portfolio using Monte Carlo simulation.
|
||||
"""
|
||||
|
||||
# %% Import dependencies ----
|
||||
# core
|
||||
import sys
|
||||
import warnings
|
||||
import gc
|
||||
from IPython import sys_info
|
||||
|
||||
# data science
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from scipy.stats import norm
|
||||
|
||||
# Cloud integration
|
||||
from azureml.core import Workspace, Dataset, ComputeTarget, VERSION as aml_version
|
||||
print(f'Azure ML SDK v{aml_version}')
|
||||
# plots
|
||||
import matplotlib.pyplot as plt
|
||||
import seaborn as sns
|
||||
|
||||
# show info about python env
|
||||
print(sys_info())
|
||||
warnings.filterwarnings("ignore")
|
||||
|
||||
|
||||
# %% Set params ----
|
||||
n_days = int(252) # US market has 252 trading days in a year
|
||||
n_simulations = int(1e4) # number of Monte-Carlo simulations
|
||||
|
||||
# The most promised currencies (copy this list from fx_currencies_analysis.Rmd)
|
||||
symbols = [
|
||||
'USD/AED', 'USD/AUD', 'USD/CHF', 'USD/CNY', 'USD/EUR', 'USD/GBP',
|
||||
'USD/HKD', 'USD/JPY', 'USD/KZT', 'USD/MXN', 'USD/RUB', 'USD/SEK', 'USD/SGD'
|
||||
]
|
||||
|
||||
|
||||
# %% Connect to Azure ML workspace ----
|
||||
ws = Workspace.from_config()
|
||||
print(f"Connected to *{ws.get_details()['friendlyName']}* workspace in *{ws.get_details()['location']}*.")
|
||||
|
||||
print('Compute Targets:')
|
||||
for compute_name in ws.compute_targets:
|
||||
compute = ws.compute_targets[compute_name]
|
||||
print('\t', compute.name, ':', compute.type)
|
||||
|
||||
# > htop
|
||||
|
||||
|
||||
# %% Load dateset ----
|
||||
currencies_ds = Dataset.get_by_name(ws, name='Currencies')
|
||||
currencies_ds.to_pandas_dataframe()
|
||||
|
||||
print(f'Dataset name: {currencies_ds.name}. Description: {currencies_ds.description}.')
|
||||
print(f'Size of Azure ML dataset object: {sys.getsizeof(currencies_ds)} bytes.')
|
||||
|
||||
|
||||
# %% Preprocessing ----
|
||||
quotes_df = (currencies_ds
|
||||
# materialize
|
||||
.to_pandas_dataframe()
|
||||
# define format
|
||||
.rename(columns={'slug': 'symbol'})
|
||||
.loc[:, ['symbol', 'date', 'close']]
|
||||
# filter
|
||||
.query("symbol in @symbols")
|
||||
.query("date > '2012-01-01'")
|
||||
# set time index
|
||||
.set_index('date')
|
||||
.sort_values(by='date'))
|
||||
|
||||
quotes_df
|
||||
|
||||
|
||||
# %% Discover data ----
|
||||
quotes_df.groupby('symbol')['close'].agg(['count', 'last'])
|
||||
|
||||
|
||||
# %% USD/RUB dataset ----
|
||||
usdrub_df = quotes_df[quotes_df.symbol == 'USD/RUB']
|
||||
usdrub_df
|
||||
|
||||
|
||||
# %% Calculate Return ----
|
||||
def calc_returns(close_prices: pd.Series) -> pd.Series:
|
||||
"""Calculate Investment Return"""
|
||||
return (close_prices/close_prices.shift()) - 1
|
||||
|
||||
|
||||
usdrub_df['diff'] = usdrub_df['close'].diff()
|
||||
usdrub_df['return'] = calc_returns(usdrub_df['close'])
|
||||
|
||||
usdrub_df[['close', 'diff', 'return']].tail(10)
|
||||
|
||||
|
||||
# %% Calculate LogReturn ----
|
||||
def calc_log_returns(return_prices: pd.Series) -> pd.Series:
|
||||
"""Calculate Log Return"""
|
||||
return np.log(1 + return_prices)
|
||||
|
||||
usdrub_df['log_return'] = usdrub_df['return'].apply(lambda x: calc_log_returns(x))
|
||||
|
||||
usdrub_df[['close', 'diff', 'return', 'log_return']].tail(10)
|
||||
|
||||
|
||||
# %% Simulate possible LogReturns ----
|
||||
|
||||
def calc_simulated_returns(log_returns: pd.Series, n_days: int, n_iterations: int) -> pd.Series:
|
||||
"""Calculate Simulated Return"""
|
||||
|
||||
u = log_returns.mean()
|
||||
var = log_returns.var()
|
||||
stdev = log_returns.std()
|
||||
|
||||
drift = u - (0.5*var)
|
||||
Z = norm.ppf(np.random.rand(n_days, n_iterations))
|
||||
|
||||
return np.exp(drift + stdev*Z)
|
||||
|
||||
|
||||
usdrub_simulated_returns = calc_simulated_returns(
|
||||
usdrub_df['log_return'].dropna(),
|
||||
n_days,
|
||||
n_simulations)
|
||||
|
||||
assert(
|
||||
usdrub_simulated_returns.shape == (n_days, n_simulations)
|
||||
and (usdrub_simulated_returns > 0).all()
|
||||
and (usdrub_simulated_returns < 2).all()
|
||||
)
|
||||
|
||||
|
||||
# %% Monte carlo simulation evaluation ----
|
||||
|
||||
def get_breakeven_prob(pred, risk_free_rate: float = 0.02) -> pd.Series:
|
||||
"""
|
||||
Calculation of the probability of a stock being above a certain threshold,
|
||||
which can be defined as a value (final stock price) or return rate (percentage change).
|
||||
"""
|
||||
|
||||
init_pred = pred.iloc[0, 0]
|
||||
|
||||
last_pred = pred.iloc[-1]
|
||||
pred_list = list(last_pred)
|
||||
|
||||
over = [(p*100)/init_pred for p in pred_list if ((p-init_pred)*100)/init_pred >= risk_free_rate]
|
||||
less = [(p*100)/init_pred for p in pred_list if ((p-init_pred)*100)/init_pred < risk_free_rate]
|
||||
|
||||
return len(over)/(len(over) + len(less))
|
||||
|
||||
|
||||
def evaluate_simulation(simulated_returns: pd.Series, last_actual_price: float, n_days: int, plot: bool = True) -> pd.DataFrame:
|
||||
"""
|
||||
Evaluate Monte-Carlo simulations result
|
||||
"""
|
||||
|
||||
# Create empty matrix
|
||||
price_list = np.zeros_like(simulated_returns)
|
||||
|
||||
# Put the last actual price in the first row,
|
||||
# and calculate the price of each day
|
||||
price_list[0] = last_actual_price
|
||||
for t in range(1, n_days):
|
||||
price_list[t] = price_list[(t - 1)]*simulated_returns[t]
|
||||
|
||||
# convert to temp dataframe
|
||||
price_df = pd.DataFrame(price_list)
|
||||
|
||||
# Plot
|
||||
if plot == True:
|
||||
x = price_df.iloc[-1]
|
||||
fig, ax = plt.subplots(1, 2, figsize=(14, 4))
|
||||
sns.distplot(x, ax=ax[0])
|
||||
sns.distplot(x, hist_kws={'cumulative': True}, kde_kws={'cumulative':True}, ax=ax[1])
|
||||
plt.xlabel('Stock Price')
|
||||
plt.show()
|
||||
|
||||
print('Results:')
|
||||
print(f'\tInvestment period: {n_days-1} days')
|
||||
print(f'\tExpected Value: {round(price_df.iloc[-1].mean(), 2)} per USD')
|
||||
print(f'\tReturn: {round(100*(price_df.iloc[-1].mean() - price_list[0,1])/price_df.iloc[-1].mean(), 2)}%')
|
||||
print(f'\tProbability of Breakeven: {get_breakeven_prob(price_df)}')
|
||||
|
||||
return price_df
|
||||
|
||||
|
||||
# %% Run Monte carlo simulation and estimate result ----
|
||||
|
||||
usdrub_mc_simulation_df = evaluate_simulation(
|
||||
usdrub_simulated_returns,
|
||||
last_actual_price=usdrub_df['close'].tail(1),
|
||||
n_days=n_days)
|
||||
|
||||
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(usdrub_mc_simulation_df.sample(10, axis='columns'))
|
||||
plt.title('USD/RUB Price Simulation')
|
||||
plt.xlabel('Days')
|
||||
plt.ylabel('RUB per $1')
|
||||
plt.ylim(10, 300)
|
||||
plt.show()
|
||||
|
||||
|
||||
# %% Monte Carlo simulation pipeline for multiple tokens ----
|
||||
|
||||
# 1. prepare
|
||||
quotes_data = [quotes_df.query('symbol == @s') for s in quotes_df.symbol.unique()]
|
||||
symbols_list = [df.symbol.unique() for df in quotes_data]
|
||||
|
||||
# 2. simulate
|
||||
returns_data = [calc_returns(df['close']) for df in quotes_data]
|
||||
log_returns_data = [calc_log_returns(r) for r in returns_data]
|
||||
simulated_returns_data = [calc_simulated_returns(lr, n_days, n_simulations) for lr in log_returns_data]
|
||||
|
||||
assert(
|
||||
len(quotes_data) > 0
|
||||
and len(quotes_data) == len(symbols_list) == len(returns_data) == len(log_returns_data) == len(simulated_returns_data)
|
||||
)
|
||||
|
||||
# 3. evaluate
|
||||
for i in range(len(symbols_list)):
|
||||
print(f'---- Starting Monte-Carlo simulation for {symbols_list[i]} symbol ----')
|
||||
|
||||
prices_ms = evaluate_simulation(simulated_returns_data[i], quotes_data[i]['close'].tail(1), n_days, plot=False)
|
||||
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(prices_ms.sample(50, axis='columns'))
|
||||
plt.title(f'{symbols_list[i]} Price Simulation')
|
||||
plt.xlabel('Days')
|
||||
plt.ylabel('Amount per $1')
|
||||
plt.show()
|
||||
|
||||
|
||||
# %% Completed ----
|
||||
gc.collect()
|
||||
|
Loading…
Reference in New Issue
Block a user