In this guided project, we will explore the relationship between the four most common world currencies over the past two decades. A side goal of this project is to study methods of analysis using visualization.
Glossary
Financial Facts
Distribution of currencies worldwide in 2021, based on their transaction value
Data Set Information
The dataset for our analysis was taken from Kaggle (Kaggle).
The author of the dataset is Daria Chemkaeva (Kaggle Expert).\
All data provided by European Central Bank Statistical Data WareHouse, EXR - Exchange Rates.
Dataset is versioned and stays on update. For current analysis was used the version from January 2021.
The exchange rates in the data set were calculated as the sum of foreign currency compared to 1 euro, which means how many units of foreign currency can be obtained by exchanging 1 euro (for example, USD/EUR = 1.322 means that for 1 euro a client can receive 1.322 US dollars).
The higher the rate, the stronger the euro, and vice versa, the lower the exchange rate, the weaker the euro.
Data Set Exploration
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import datetime as dt
exchange_rates = pd.read_csv('euro-daily-hist_1999_2020.csv')
exchange_rates
Period\Unit: | [Australian dollar ] | [Bulgarian lev ] | [Brazilian real ] | [Canadian dollar ] | [Swiss franc ] | [Chinese yuan renminbi ] | [Cypriot pound ] | [Czech koruna ] | [Danish krone ] | ... | [Romanian leu ] | [Russian rouble ] | [Swedish krona ] | [Singapore dollar ] | [Slovenian tolar ] | [Slovak koruna ] | [Thai baht ] | [Turkish lira ] | [US dollar ] | [South African rand ] | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2021-01-08 | 1.5758 | 1.9558 | 6.5748 | 1.5543 | 1.0827 | 7.9184 | NaN | 26.163 | 7.4369 | ... | 4.8708 | 90.8000 | 10.0510 | 1.6228 | NaN | NaN | 36.8480 | 9.0146 | 1.2250 | 18.7212 |
1 | 2021-01-07 | 1.5836 | 1.9558 | 6.5172 | 1.5601 | 1.0833 | 7.9392 | NaN | 26.147 | 7.4392 | ... | 4.8712 | 91.2000 | 10.0575 | 1.6253 | NaN | NaN | 36.8590 | 8.9987 | 1.2276 | 18.7919 |
2 | 2021-01-06 | 1.5824 | 1.9558 | 6.5119 | 1.5640 | 1.0821 | 7.9653 | NaN | 26.145 | 7.4393 | ... | 4.8720 | 90.8175 | 10.0653 | 1.6246 | NaN | NaN | 36.9210 | 9.0554 | 1.2338 | 18.5123 |
3 | 2021-01-05 | 1.5927 | 1.9558 | 6.5517 | 1.5651 | 1.0803 | 7.9315 | NaN | 26.227 | 7.4387 | ... | 4.8721 | 91.6715 | 10.0570 | 1.6180 | NaN | NaN | 36.7760 | 9.0694 | 1.2271 | 18.4194 |
4 | 2021-01-04 | 1.5928 | 1.9558 | 6.3241 | 1.5621 | 1.0811 | 7.9484 | NaN | 26.141 | 7.4379 | ... | 4.8713 | 90.3420 | 10.0895 | 1.6198 | NaN | NaN | 36.7280 | 9.0579 | 1.2296 | 17.9214 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
5694 | 1999-01-08 | 1.8406 | NaN | NaN | 1.7643 | 1.6138 | NaN | 0.58187 | 34.938 | 7.4433 | ... | 1.3143 | 27.2075 | 9.1650 | 1.9537 | 188.8400 | 42.560 | 42.5590 | 0.3718 | 1.1659 | 6.7855 |
5695 | 1999-01-07 | 1.8474 | NaN | NaN | 1.7602 | 1.6165 | NaN | 0.58187 | 34.886 | 7.4431 | ... | 1.3092 | 26.9876 | 9.1800 | 1.9436 | 188.8000 | 42.765 | 42.1678 | 0.3701 | 1.1632 | 6.8283 |
5696 | 1999-01-06 | 1.8820 | NaN | NaN | 1.7711 | 1.6116 | NaN | 0.58200 | 34.850 | 7.4452 | ... | 1.3168 | 27.4315 | 9.3050 | 1.9699 | 188.7000 | 42.778 | 42.6949 | 0.3722 | 1.1743 | 6.7307 |
5697 | 1999-01-05 | 1.8944 | NaN | NaN | 1.7965 | 1.6123 | NaN | 0.58230 | 34.917 | 7.4495 | ... | 1.3168 | 26.5876 | 9.4025 | 1.9655 | 188.7750 | 42.848 | 42.5048 | 0.3728 | 1.1790 | 6.7975 |
5698 | 1999-01-04 | 1.9100 | NaN | NaN | 1.8004 | 1.6168 | NaN | 0.58231 | 35.107 | 7.4501 | ... | 1.3111 | 25.2875 | 9.4696 | 1.9554 | 189.0450 | 42.991 | 42.6799 | 0.3723 | 1.1789 | 6.9358 |
5699 rows × 41 columns
exchange_rates.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5699 entries, 0 to 5698 Data columns (total 41 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Period\Unit: 5699 non-null object 1 [Australian dollar ] 5699 non-null object 2 [Bulgarian lev ] 5297 non-null object 3 [Brazilian real ] 5431 non-null object 4 [Canadian dollar ] 5699 non-null object 5 [Swiss franc ] 5699 non-null object 6 [Chinese yuan renminbi ] 5431 non-null object 7 [Cypriot pound ] 2346 non-null object 8 [Czech koruna ] 5699 non-null object 9 [Danish krone ] 5699 non-null object 10 [Estonian kroon ] 3130 non-null object 11 [UK pound sterling ] 5699 non-null object 12 [Greek drachma ] 520 non-null object 13 [Hong Kong dollar ] 5699 non-null object 14 [Croatian kuna ] 5431 non-null object 15 [Hungarian forint ] 5699 non-null object 16 [Indonesian rupiah ] 5699 non-null object 17 [Israeli shekel ] 5431 non-null object 18 [Indian rupee ] 5431 non-null object 19 [Iceland krona ] 3292 non-null float64 20 [Japanese yen ] 5699 non-null object 21 [Korean won ] 5699 non-null object 22 [Lithuanian litas ] 4159 non-null object 23 [Latvian lats ] 3904 non-null object 24 [Maltese lira ] 2346 non-null object 25 [Mexican peso ] 5699 non-null object 26 [Malaysian ringgit ] 5699 non-null object 27 [Norwegian krone ] 5699 non-null object 28 [New Zealand dollar ] 5699 non-null object 29 [Philippine peso ] 5699 non-null object 30 [Polish zloty ] 5699 non-null object 31 [Romanian leu ] 5637 non-null float64 32 [Russian rouble ] 5699 non-null object 33 [Swedish krona ] 5699 non-null object 34 [Singapore dollar ] 5699 non-null object 35 [Slovenian tolar ] 2085 non-null object 36 [Slovak koruna ] 2608 non-null object 37 [Thai baht ] 5699 non-null object 38 [Turkish lira ] 5637 non-null float64 39 [US dollar ] 5699 non-null object 40 [South African rand ] 5699 non-null object dtypes: float64(3), object(38) memory usage: 1.8+ MB
print("The file contains", len(exchange_rates.columns), "columns and", len(exchange_rates.index), "rows" )
print('Since there are columns with fewer non-null values than the number of file rows , \
hence null values are present in the data.\n\
There are 3 numeric columns (float64) and 38 columns with data stored as object.')
The file contains 41 columns and 5699 rows Since there are columns with fewer non-null values than the number of file rows , hence null values are present in the data. There are 3 numeric columns (float64) and 38 columns with data stored as object.
Currencies Selection
exchange_rates.to_csv('euro-daily-hist_cleaned.csv', index = False)
rates_selected = pd.read_csv('euro-daily-hist_cleaned.csv')
rates_selected = rates_selected[['Period\\Unit:', '[US dollar ]', '[UK pound sterling ]', '[Chinese yuan renminbi ]']].copy()
rates_selected.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5699 entries, 0 to 5698 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Period\Unit: 5699 non-null object 1 [US dollar ] 5699 non-null object 2 [UK pound sterling ] 5699 non-null object 3 [Chinese yuan renminbi ] 5431 non-null object dtypes: object(4) memory usage: 178.2+ KB
Exchange rates meaning:
Data Preparation
rates_selected.rename(columns={'[US dollar ]': 'USD', '[UK pound sterling ]': 'GBP', '[Chinese yuan renminbi ]': 'CNY',
'Period\\Unit:': 'Time'},
inplace=True)
rates_selected['Time'] = pd.to_datetime(rates_selected['Time'])
rates_selected.sort_values('Time', inplace=True)
rates_selected.reset_index(drop=True, inplace=True)
rates_selected.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5699 entries, 0 to 5698 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Time 5699 non-null datetime64[ns] 1 USD 5699 non-null object 2 GBP 5699 non-null object 3 CNY 5431 non-null object dtypes: datetime64[ns](1), object(3) memory usage: 178.2+ KB
Section A.1. USD data cleaning
rates_selected['USD'].value_counts().sort_index()
- 62 0.8252 1 0.8307 1 0.8324 1 0.8377 1 .. 1.5919 1 1.5928 1 1.5931 1 1.5940 1 1.5990 1 Name: USD, Length: 3528, dtype: int64
# there are 62 rows with value "-" that should be removed and the data should be changed to number format
rates_selected = rates_selected.loc[rates_selected['USD']!='-']
rates_selected['USD']= rates_selected['USD'].astype(float)
rates_selected['USD'].describe()
count 5637.000000 mean 1.199704 std 0.162328 min 0.825200 25% 1.098200 50% 1.202300 75% 1.320300 max 1.599000 Name: USD, dtype: float64
Section A.2. GBP data cleaning
rates_selected['GBP'].value_counts().sort_index()# thanks to actions above we do not need to clean the dataset
0.57110 1 0.57600 1 0.57700 1 0.57710 1 0.57940 1 .. 0.95090 1 0.95250 1 0.96100 1 0.97420 1 0.97855 1 Name: GBP, Length: 3469, dtype: int64
# converting data to number format
rates_selected['GBP']= rates_selected['GBP'].astype(float)
rates_selected['GBP'].describe()
count 5637.000000 mean 0.768002 std 0.100683 min 0.571100 25% 0.677550 50% 0.788600 75% 0.862900 max 0.978550 Name: GBP, dtype: float64
Section A.3. CNY data cleanup
rates_selected['CNY'].value_counts().sort_index()# again the value '-' already removed
10.0003 1 10.0013 1 10.0023 1 10.0032 1 10.0036 1 .. 9.9928 1 9.9936 1 9.9958 1 9.9986 1 9.9997 1 Name: CNY, Length: 4798, dtype: int64
# converting data to number format
rates_selected['CNY']= rates_selected['CNY'].astype(float)
rates_selected['CNY'].describe()
count 5370.000000 mean 8.606695 std 1.160179 min 6.555200 25% 7.704200 50% 8.226500 75% 9.661500 max 11.284000 Name: CNY, dtype: float64
Section A.5. Rolling Window and Removing NaN values
# Rolling Windows (30 days)
rates_selected =rates_selected.copy()
rates_selected['rolling_mean_USD'] = rates_selected['USD'].rolling(30).mean()
rates_selected['rolling_mean_GBP'] = rates_selected['GBP'].rolling(30).mean()
rates_selected['rolling_mean_CNY'] = rates_selected['CNY'].rolling(30).mean()
rates_selected
Time | USD | GBP | CNY | rolling_mean_USD | rolling_mean_GBP | rolling_mean_CNY | |
---|---|---|---|---|---|---|---|
0 | 1999-01-04 | 1.1789 | 0.71110 | NaN | NaN | NaN | NaN |
1 | 1999-01-05 | 1.1790 | 0.71220 | NaN | NaN | NaN | NaN |
2 | 1999-01-06 | 1.1743 | 0.70760 | NaN | NaN | NaN | NaN |
3 | 1999-01-07 | 1.1632 | 0.70585 | NaN | NaN | NaN | NaN |
4 | 1999-01-08 | 1.1659 | 0.70940 | NaN | NaN | NaN | NaN |
... | ... | ... | ... | ... | ... | ... | ... |
5694 | 2021-01-04 | 1.2296 | 0.90160 | 7.9484 | 1.211170 | 0.902912 | 7.928793 |
5695 | 2021-01-05 | 1.2271 | 0.90333 | 7.9315 | 1.212530 | 0.903225 | 7.933457 |
5696 | 2021-01-06 | 1.2338 | 0.90635 | 7.9653 | 1.213987 | 0.903807 | 7.938373 |
5697 | 2021-01-07 | 1.2276 | 0.90190 | 7.9392 | 1.215357 | 0.904200 | 7.942507 |
5698 | 2021-01-08 | 1.2250 | 0.90128 | 7.9184 | 1.216557 | 0.904533 | 7.945823 |
5637 rows × 7 columns
# Removing NaN values (since the first 30 days have nothing to compare, they naturally got null values, plus, some CNY data was missing)
rates_selected= rates_selected.dropna()
rates_selected.shape[0]
5341
Final result
rates_selected.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 5341 entries, 297 to 5698 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Time 5341 non-null datetime64[ns] 1 USD 5341 non-null float64 2 GBP 5341 non-null float64 3 CNY 5341 non-null float64 4 rolling_mean_USD 5341 non-null float64 5 rolling_mean_GBP 5341 non-null float64 6 rolling_mean_CNY 5341 non-null float64 dtypes: datetime64[ns](1), float64(6) memory usage: 333.8 KB
print('Now we have', rates_selected.shape[0], 'rows in the data set for further analysis in the time interval from', rates_selected['Time'].dt.date.min(),'to',
rates_selected['Time'].dt.date.max())
Now we have 5341 rows in the data set for further analysis in the time interval from 2000-02-23 to 2021-01-08
Many aspects affect exchange rates such as economic state, political issues, government measures to appreciate the currency, etc.
Some events change exchange rates more, others have less effect.
In this chapter, we are going to analyze the following theses:
We will study euro steadiness using USD/EUR, GBP/EUR and CNY/EUR exchange rates.
Note. We will use virtualization methods and leave numbers and statistics behind the scenes.
The difference between the moving average and the nominal value is negligible, so we can assume these values are equal in our analysis.
U.S. Dollar vs Euro
plt.figure(figsize = (8, 3))
plt.plot(rates_selected['Time'], rates_selected['rolling_mean_USD'])
plt.title('USD vs EUR from 2000-02-23 to 2021-01-08', fontsize = 14, weight='bold')
plt.xlabel('Years', fontsize=10, weight = 'bold')
plt.ylabel('Exchange Rate', size=10, weight= 'bold')
plt.tick_params(left=False)
plt.yticks([])
plt.axhline(y = 1.2, color = 'red', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 1.22, 'In average', size=10, color='red', weight ='light', alpha =0.8)
plt.axhline(y = 1.0, color = 'green', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 1.02, '1USD=1EUR', size=10, color='green', weight ='light', alpha =0.8)
plt.show()
The chart above showed that after several years of weakness after the introduction of the euro, it strengthened its position against the US dollar. Since the end of 2003, the euro has remained stronger than the US dollar. Even when the exchange rate fell at the end of 2015, it remains above 1.
It can be said that the euro is more resilient to global circumstances than the US dollar.
British Pound vs Euro
plt.figure(figsize = (8, 3))
plt.plot(rates_selected['Time'], rates_selected['rolling_mean_GBP'])
plt.title('GBP vs EUR from 2000-02-23 to 2021-01-08', fontsize = 14, weight='bold')
plt.xlabel('Years', fontsize=10, weight = 'bold')
plt.ylabel('Exchange Rate', size=10, weight= 'bold')
plt.tick_params(left=False)
plt.yticks([])
plt.axhline(y = 0.77, color = 'red', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 0.78, 'In average', size=10, color='red', weight ='light', alpha =0.8)
plt.axhline(y = 1.0, color = 'green', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 0.98, '1GBP=1EUR', size=10, color='green', weight ='light', alpha =0.8)
plt.show()
The chart above showed that from 2000 to 2008, the euro appreciated relatively slowly against the British pound. But even in its best days, the euro did not reach the equivalence of the pound.
We can say that the euro is weaker than the British pound in nominal terms.
Chinese Yuan vs Euro
plt.figure(figsize = (8, 3))
plt.plot(rates_selected['Time'], rates_selected['rolling_mean_CNY'])
plt.title('CNY vs EUR from 2000-02-23 to 2021-01-08', fontsize = 14, weight='bold')
plt.xlabel('Years', fontsize=10, weight = 'bold')
plt.ylabel('Exchange Rate', size=10, weight= 'bold')
plt.tick_params(left=False)
plt.yticks([])
plt.axhline(y = 8.6, color = 'red', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 8.7, 'In average', size=10, color='red', weight ='light', alpha =0.8)
plt.axhline(y = 7.0, color = 'green', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 6.7, '7CNY=1EUR', size=10, color='green', weight ='light', alpha =0.8)
plt.axhline(y = 10.0, color = 'green', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 10.2, '10CNY=1EUR', size=10, color='green', weight ='light', alpha =0.8)
plt.show()
The chart above shows that from 2000 to 2005, the euro strengthened against the Chinese yuan. Between 2005 and 2010, the euro remained much stronger than the yuan, after which the CNY/EUR exchange rate plummeted.
However, the yuan never reached the equivalence of the euro.
It is difficult to say how much more stable the euro is than the Chinese yuan. Without a doubt, the euro is worth more than the yuan.
Comparison of exchange rates over two decades
rates_selected =rates_selected.copy()
rates_selected['year_mean_USD'] = rates_selected['USD'].rolling(180).mean()
rates_selected['year_mean_GBP'] = rates_selected['GBP'].rolling(180).mean()
rates_selected['year_mean_CNY'] = rates_selected['CNY'].rolling(180).mean()
rates_selected.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 5341 entries, 297 to 5698 Data columns (total 10 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Time 5341 non-null datetime64[ns] 1 USD 5341 non-null float64 2 GBP 5341 non-null float64 3 CNY 5341 non-null float64 4 rolling_mean_USD 5341 non-null float64 5 rolling_mean_GBP 5341 non-null float64 6 rolling_mean_CNY 5341 non-null float64 7 year_mean_USD 5162 non-null float64 8 year_mean_GBP 5162 non-null float64 9 year_mean_CNY 5162 non-null float64 dtypes: datetime64[ns](1), float64(9) memory usage: 459.0 KB
currency = ['USD/EUR', 'GBP/EUR', 'CNY/EUR']
fig, ax = plt.subplots(figsize=(8, 4))
plt.plot(rates_selected['Time'], rates_selected['year_mean_USD'], label = 'USD/EUR')
plt.plot(rates_selected['Time'], rates_selected['year_mean_GBP'], label = 'GBP/EUR')
plt.plot(rates_selected['Time'], rates_selected['year_mean_CNY'], label = 'CNY/EUR')
plt.title('What is stronger, young Euro or older currencies?', fontsize = 14, weight='bold')
plt.xlabel('Years', fontsize=10, weight = 'bold')
plt.ylabel('Exchange Rate', size=10, weight= 'bold')
plt.tick_params(left=False)
plt.yticks([])
plt.axhline(y = 5, color = 'red', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 5.4, 'In average (5 units = 1 euro)', size=10, color='red', weight ='light', alpha =0.8)
plt.axhline(y = 1, color = 'purple', linewidth=1)
plt.text(dt.date(2000, 1, 10), 1.2, 'Equivalent (1 currency = 1EUR)', size=10, color='purple', weight ='light')
plt.axhline(y = 10, color = 'purple', linewidth=1)
plt.text(dt.date(2000, 1, 10), 10.2, '10 units (10 currency = 1EUR)', size=10, color='purple', weight ='light')
plt.legend(currency, loc = 'center right', fancybox=True, framealpha = 1, borderpad = 1, shadow = True)
plt.show()
Comparative analysis in the chart above showed the following:
Variable Assignment
# Variable assignment looks like a rather primitive method, but it actually makes charting easier and actually doesn't require too much manual work.
nominal_min_USD = rates_selected['USD'].min().round(3)
nominal_min_GBP = rates_selected['GBP'].min().round(3)
nominal_min_CNY = rates_selected['CNY'].min().round(3)
nominal_max_USD = rates_selected['USD'].max().round(3)
nominal_max_GBP = rates_selected['GBP'].max().round(3)
nominal_max_CNY = rates_selected['CNY'].max().round(3)
nominal_mean_USD = rates_selected['USD'].mean().round(3)
nominal_mean_GBP = rates_selected['GBP'].mean().round(3)
nominal_mean_CNY = rates_selected['CNY'].mean().round(3)
rw_30_min_USD = rates_selected['rolling_mean_USD'].min().round(3)
rw_30_min_GBP = rates_selected['rolling_mean_GBP'].min().round(3)
rw_30_min_CNY = rates_selected['rolling_mean_CNY'].min().round(3)
rw_30_max_USD = rates_selected['rolling_mean_USD'].max().round(3)
rw_30_max_GBP = rates_selected['rolling_mean_GBP'].max().round(3)
rw_30_max_CNY = rates_selected['rolling_mean_CNY'].max().round(3)
rw_30_mean_USD = rates_selected['rolling_mean_USD'].mean().round(3)
rw_30_mean_GBP = rates_selected['rolling_mean_GBP'].mean().round(3)
rw_30_mean_CNY = rates_selected['rolling_mean_CNY'].mean().round(3)
rw_180_min_USD = rates_selected['year_mean_USD'].min().round(3)
rw_180_min_GBP = rates_selected['year_mean_GBP'].min().round(3)
rw_180_min_CNY = rates_selected['year_mean_CNY'].min().round(3)
rw_180_max_USD = rates_selected['year_mean_USD'].max().round(3)
rw_180_max_GBP = rates_selected['year_mean_GBP'].max().round(3)
rw_180_max_CNY = rates_selected['year_mean_CNY'].max().round(3)
rw_180_mean_USD= rates_selected['year_mean_USD'].mean().round(3)
rw_180_mean_GBP = rates_selected['year_mean_GBP'].mean().round(3)
rw_180_mean_CNY = rates_selected['year_mean_CNY'].mean().round(3)
Determination of Accuracy
fig, ax= plt.subplots(figsize=(10, 4))
fig = plt.title('Determination of Accuracy', size = 12, weight = 'bold', pad = 35)
plt.suptitle('Comparative analysis of nominal exchange rates,\n30-days moving average and 180-days moving average' , size = 11)
plt.bar([1, 2, 3], [nominal_min_USD, nominal_min_GBP , nominal_min_CNY], color = 'lightgreen', width = 0.2, label = 'Nominal')
plt.bar([1.2, 2.2, 3.2], [rw_30_min_USD, rw_30_min_GBP, rw_30_min_CNY], color= 'royalblue', width = 0.2, label = 'MA 30 days')
plt.bar([1.4, 2.4, 3.4], [rw_180_min_USD, rw_180_min_GBP, rw_180_min_CNY], color= 'coral', width = 0.2, label= 'MA 180 days')
plt.bar([4, 5, 6 ], [nominal_mean_USD, nominal_mean_GBP , nominal_mean_CNY], color = 'lightgreen', width = 0.2)
plt.bar([4.2, 5.2, 6.2], [rw_30_mean_USD, rw_30_mean_GBP, rw_30_mean_CNY], color= 'royalblue', width = 0.2)
plt.bar([4.4, 5.4, 6.4], [rw_180_mean_USD, rw_180_mean_GBP, rw_180_mean_CNY], color = 'coral', width = 0.2)
plt.bar([7, 8, 9 ], [nominal_max_USD, nominal_max_GBP , nominal_max_CNY], color = 'lightgreen', width = 0.2)
plt.bar([7.2, 8.2, 9.2], [rw_30_max_USD, rw_30_max_GBP, rw_30_max_CNY], color= 'royalblue', width = 0.2)
plt.bar([7.4, 8.4, 9.4], [rw_180_max_USD, rw_180_max_GBP, rw_180_max_CNY], color= 'coral', width = 0.2)
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('Exchange Rate', size=10, weight= 'bold')
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True)
plt.text(x=0.6,y=1.5, s="USD/EUR min", size=10)
plt.text(x=1.6,y=0.9, s='GBP/EUR min', size=10)
plt.text(x=2.6,y=7.2, s="CNY/EUR min", size=10)
plt.text(x=3.6,y=1.7, s="USD/EUR mean", size=10)
plt.text(x=4.6,y=1.1, s="GBP/EUR mean", size=10)
plt.text(x=5.6,y=9, s="CNY/EUR mean", size=10)
plt.text(x=6.6,y=1.8, s="USD/EUR max", size=10)
plt.text(x=7.6,y=1.2, s="GBP/EUR max", size=10)
plt.text(x=8.6,y=11.5, s="CNY/EUR max", size=10)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
Result
Comparative analysis of nominal exchange rates, 30-day moving average and 180-day moving average showed that the values of all three types can be equivalent for long-term analysis in order to identify tendences. However, the difference is noticeable, so it is better to use nominal values for statistical analysis.
Statistical Analysis of Exchange Rates in Nominal Value
fig, ax = plt.subplots(figsize=(8, 3))
plt.title('Statistical Analysis of Exchange Rates in Nominal Value', size = 12, weight = 'bold')
plt.bar([1, 1.3, 1.6], [nominal_min_USD, nominal_mean_USD, nominal_max_USD], color = 'lightgreen', width = 0.3, label = 'USD/EUR')
plt.bar([2, 2.3, 2.6], [nominal_min_GBP, nominal_mean_GBP, nominal_max_GBP], color = 'royalblue', width = 0.3, label = 'GBP/EUR')
plt.bar([3, 3.3, 3.6], [nominal_min_CNY, nominal_mean_CNY, nominal_max_CNY], color = 'coral', width = 0.3, label = 'CNY/EUR')
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True)
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('Exchange Rate', size=10, weight= 'bold')
plt.text(x=0.9,y=1, s="min", size=10)
plt.text(x=1.9,y=0.9, s="min", size=10)
plt.text(x=2.9,y=7, s="min", size=10)
plt.text(x=1.15,y=1.3, s="mean", size=10)
plt.text(x=2.15,y=1.1, s="mean", size=10)
plt.text(x=3.15,y=9, s="mean", size=10)
plt.text(x=1.5,y=1.7, s="max", size=10)
plt.text(x=2.5,y=1.4, s="max", size=10)
plt.text(x=3.5,y=11.5, s="max", size=10)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
Result
The chart above showed that the difference between the minimum, average and maximum values of the exchange rates is large enough to be noticed.
From this angle, the euro doesn't look stable enough.
Also we can say following:
To be sure of our conclusion, let's look at the percentage.
Statistical Analysis of Exchange Rates in Percents
mean_min_USD = ((nominal_mean_USD/ nominal_min_USD*100) - 100).round(3)
max_min_USD = ((nominal_max_USD/ nominal_min_USD*100) - 100).round(3)
mean_min_GBP = ((nominal_mean_GBP/ nominal_min_GBP*100) - 100).round(3)
max_min_GBP = ((nominal_max_GBP/ nominal_min_GBP*100) - 100).round(3)
mean_min_CNY = ((nominal_mean_CNY/ nominal_min_CNY*100) - 100).round(3)
max_min_CNY = ((nominal_max_CNY/ nominal_min_CNY*100) - 100).round(3)
fig, ax = plt.subplots(figsize=(7, 5))
plt.title('Change of Exchange Rates in Percents', size = 12, weight = 'bold')
plt.bar([1, 1.3], [mean_min_USD, max_min_USD], color = 'lightgreen', width = 0.3, label = 'USD/EUR')
plt.bar([2, 2.3], [mean_min_GBP, max_min_GBP], color = 'royalblue', width = 0.3, label = 'GBP/EUR')
plt.bar([3, 3.3], [mean_min_CNY, max_min_CNY], color = 'coral', width = 0.3, label = 'CNY/EUR')
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True)
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('Growth of Exchange Rates in Percents ', size=10, weight= 'bold')
plt.text(x=0.83,y=(round(mean_min_USD)-3), s="Mean/Min", size=10, weight= 'bold')
plt.text(x=1.83,y=(round(mean_min_GBP)-3), s="Mean/Min", size=10, weight= 'bold')
plt.text(x=2.83,y=(round(mean_min_CNY)-3), s="Mean/Min", size=10, weight= 'bold')
plt.text(x=1.13,y=(round(max_min_USD)-3), s="Max/Min", size=10, weight= 'bold')
plt.text(x=2.13,y=(round(max_min_GBP)-3), s="Max/Min", size=10, weight= 'bold')
plt.text(x=3.13,y=(round(max_min_CNY)-3), s="Max/Min", size=10, weight= 'bold')
plt.axhline(y = 25, color = 'red', linewidth=1, alpha= 0.8)
plt.axhline(y = 50, color = 'red', linewidth=1, alpha= 0.8)
plt.axhline(y = 75, color = 'red', linewidth=1, alpha= 0.8)
plt.text(0.8, 26, ' growth 25%', size=10, color='red', weight ='light', alpha =0.8)
plt.text(0.8, 51, ' growth 50%', size=10, color='red', weight ='light', alpha =0.8)
plt.text(0.8, 76, ' growth 75%', size=10, color='red', weight ='light', alpha =0.8)
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
Result
And here we got a rather unexpected picture:
The goal of analysis of this chapter is to find if the change of exchange rates was even dramatic (10% and more per day), so, we will not use the real Volatility formula
(WallStreetMojo), instead we will use standart statiatics.
Volatility below was calculated as "volatility = ((Exchange Rate Nominal "Day" / Exchange Rate Nominal "Day-1")x100)-100. round(4)".
To make the calculations the given .csv file was saved as Microsoft Excel Sheet (.xlsx), formated after calculation, cleaned and converted back to .csv file.
volatility = pd.read_csv('euro-selected_1.csv')
volatility['Time'] = pd.to_datetime(volatility['Time'])
volatility = volatility.dropna()
volatility.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 5329 entries, 0 to 5368 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Time 5329 non-null datetime64[ns] 1 CNY 5329 non-null float64 2 CNY/EUR % 5329 non-null float64 3 GBP 5329 non-null float64 4 GBP/EUR % 5329 non-null float64 5 USD 5329 non-null float64 6 USD/EUR % 5329 non-null float64 dtypes: datetime64[ns](1), float64(6) memory usage: 333.1 KB
Percent Change in Exchange Rates (1999 - 2005)
vol_1999_2005 = volatility.copy()[(volatility['Time'].dt.year >=1998)&(volatility['Time'].dt.year <=2005)]
vol_1999_2005.shape
(1507, 7)
v_min_1999_2005_USD= vol_1999_2005['USD/EUR %'].min().round(3)
v_min_1999_2005_GBP = vol_1999_2005['GBP/EUR %'].min().round(3)
v_min_1999_2005_CNY = vol_1999_2005['CNY/EUR %'].min().round(3)
v_max_1999_2005_USD = vol_1999_2005['USD/EUR %'].max().round(3)
v_max_1999_2005_GBP = vol_1999_2005['GBP/EUR %'].max().round(3)
v_max_1999_2005_CNY = vol_1999_2005['CNY/EUR %'].max().round(3)
v_mean_1999_2005_USD = vol_1999_2005['USD/EUR %'].mean().round(3)
v_mean_1999_2005_GBP = vol_1999_2005['GBP/EUR %'].mean().round(3)
v_mean_1999_2005_CNY = vol_1999_2005['CNY/EUR %'].mean().round(3)
fig, ax = plt.subplots(figsize=(8, 5))
fig = plt.title('Percent Change in Exchange Rates (1999 - 2005)', size = 12, weight = 'bold', pad = 42)
plt.suptitle('Comparative analysis of exchange rate volatility,\nas a percentage of daily change' , size = 10)
plt.bar([1, 1.3, 1.6], [v_min_1999_2005_USD, v_mean_1999_2005_USD, v_max_1999_2005_USD], color = 'lightgreen', width = 0.3, label = 'USD/EUR')
plt.bar([2, 2.3, 2.6], [v_min_1999_2005_GBP, v_mean_1999_2005_GBP, v_max_1999_2005_GBP], color = 'royalblue', width = 0.3, label = 'GBP/EUR')
plt.bar([3, 3.3, 3.6], [v_min_1999_2005_CNY, v_mean_1999_2005_CNY, v_max_1999_2005_CNY], color = 'coral', width = 0.3, label = 'CNY/EUR')
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'lower right')
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('% of Daily Change', size=10, weight= 'bold')
plt.text(x=0.9,y=0.1, s="min", size=10)
plt.text(x=1.9,y=0.1, s="min", size=10)
plt.text(x=2.9,y=0.1, s="min", size=10)
plt.text(x=1.2,y=0.1, s="mean", size=10)
plt.text(x=2.2,y=0.1, s="mean", size=10)
plt.text(x=3.2,y=0.1, s="mean", size=10)
plt.text(x=1.5,y=4.4, s="max", size=10)
plt.text(x=2.5,y=2.3, s="max", size=10)
plt.text(x=3.5,y=4.4, s="max", size=10)
plt.axhline(y = 0, color = 'black', linewidth=1)
plt.axhline(y = 2, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = -2, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = 4, color = 'red', linewidth=1, alpha = 0.7)
plt.text(x=0.8,y=4.2, s="4%", size=10, color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=2.2, s="2%", size=10, color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=-1.8, s="-2%", color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=0.2, s="0%", color='red', weight ='light', alpha =0.8)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
We see that between 1999 and 2005:
Percent Change in Exchange Rates (2006 - 2010)
vol_2006_2010 = volatility.copy()[(volatility['Time'].dt.year >=2006)&(volatility['Time'].dt.year <=2010)]
vol_2006_2010.shape
(1263, 7)
v_min_2006_2010_USD= vol_2006_2010['USD/EUR %'].min().round(3)
v_min_2006_2010_GBP = vol_2006_2010['GBP/EUR %'].min().round(3)
v_min_2006_2010_CNY = vol_2006_2010['CNY/EUR %'].min().round(3)
v_max_2006_2010_USD = vol_2006_2010['USD/EUR %'].max().round(3)
v_max_2006_2010_GBP = vol_2006_2010['GBP/EUR %'].max().round(3)
v_max_2006_2010_CNY = vol_2006_2010['CNY/EUR %'].max().round(3)
v_mean_2006_2010_USD = vol_2006_2010['USD/EUR %'].mean().round(3)
v_mean_2006_2010_GBP = vol_2006_2010['GBP/EUR %'].mean().round(3)
v_mean_2006_2010_CNY = vol_2006_2010['CNY/EUR %'].mean().round(3)
fig, ax = plt.subplots(figsize=(8, 5))
fig = plt.title('Percent Change in Exchange Rates (2006 - 2010)', size = 12, weight = 'bold', pad = 42)
plt.suptitle('Comparative analysis of exchange rate volatility,\nas a percentage of daily change' , size = 10)
plt.bar([1, 1.3, 1.6], [v_min_2006_2010_USD, v_mean_2006_2010_USD, v_max_2006_2010_USD], color = 'lightgreen', width = 0.3, label = 'USD/EUR')
plt.bar([2, 2.3, 2.6], [v_min_2006_2010_GBP, v_mean_2006_2010_GBP, v_max_2006_2010_GBP], color = 'royalblue', width = 0.3, label = 'GBP/EUR')
plt.bar([3, 3.3, 3.6], [v_min_2006_2010_CNY, v_mean_2006_2010_CNY, v_max_2006_2010_CNY], color = 'coral', width = 0.3, label = 'CNY/EUR')
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'lower right')
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('% of Daily Change', size=10, weight= 'bold')
plt.text(x=0.9,y=0.1, s="min", size=10)
plt.text(x=1.9,y=0.1, s="min", size=10)
plt.text(x=2.9,y=0.1, s="min", size=10)
plt.text(x=1.2,y=0.1, s="mean", size=10)
plt.text(x=2.2,y=0.1, s="mean", size=10)
plt.text(x=3.2,y=0.1, s="mean", size=10)
plt.text(x=1.5,y=4.4, s="max", size=10)
plt.text(x=2.5,y=2.3, s="max", size=10)
plt.text(x=3.5,y=4.4, s="max", size=10)
plt.axhline(y = 0, color = 'black', linewidth=1)
plt.axhline(y = 2, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = -2, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = 4, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = -4, color = 'red', linewidth=1, alpha = 0.7)
plt.text(x=0.8,y=4.2, s="4%", size=10, color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=2.2, s="2%", size=10, color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=-1.8, s="-2%", color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=0.2, s="0%", color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=-3.8, s="-4%", size=10, color='red', weight ='light', alpha =0.8)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
Looking at the time between 2006 and 2010, we see:
Percent Change in Exchange Rates (2011 - 2015)
vol_2011_2015 = volatility.copy()[(volatility['Time'].dt.year >=2011)&(volatility['Time'].dt.year <=2015)]
vol_2011_2015.shape
(1275, 7)
v_min_2011_2015_USD= vol_2011_2015['USD/EUR %'].min().round(3)
v_min_2011_2015_GBP = vol_2011_2015['GBP/EUR %'].min().round(3)
v_min_2011_2015_CNY = vol_2011_2015['CNY/EUR %'].min().round(3)
v_max_2011_2015_USD = vol_2011_2015['USD/EUR %'].max().round(3)
v_max_2011_2015_GBP = vol_2011_2015['GBP/EUR %'].max().round(3)
v_max_2011_2015_CNY = vol_2011_2015['CNY/EUR %'].max().round(3)
v_mean_2011_2015_USD = vol_2011_2015['USD/EUR %'].mean().round(3)
v_mean_2011_2015_GBP = vol_2011_2015['GBP/EUR %'].mean().round(3)
v_mean_2011_2015_CNY = vol_2011_2015['CNY/EUR %'].mean().round(3)
fig, ax = plt.subplots(figsize=(8, 5))
fig = plt.title('Percent Change in Exchange Rates (2011 - 2015)', size = 12, weight = 'bold', pad = 42)
plt.suptitle('Comparative analysis of exchange rate volatility,\nas a percentage of daily change' , size = 10)
plt.bar([1, 1.3, 1.6], [v_min_2011_2015_USD, v_mean_2011_2015_USD, v_max_2011_2015_USD], color = 'lightgreen', width = 0.3, label = 'USD/EUR')
plt.bar([2, 2.3, 2.6], [v_min_2011_2015_GBP, v_mean_2011_2015_GBP, v_max_2011_2015_GBP], color = 'royalblue', width = 0.3, label = 'GBP/EUR')
plt.bar([3, 3.3, 3.6], [v_min_2011_2015_CNY, v_mean_2011_2015_CNY, v_max_2011_2015_CNY], color = 'coral', width = 0.3, label = 'CNY/EUR')
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'lower right')
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('% of Daily Change', size=10, weight= 'bold')
plt.text(x=0.9,y=0.1, s="min", size=10)
plt.text(x=1.9,y=0.1, s="min", size=10)
plt.text(x=2.9,y=0.1, s="min", size=10)
plt.text(x=1.2,y=0.1, s="mean", size=10)
plt.text(x=2.2,y=0.1, s="mean", size=10)
plt.text(x=3.2,y=0.1, s="mean", size=10)
plt.text(x=1.5,y=2.4, s="max", size=10)
plt.text(x=2.5,y=2.1, s="max", size=10)
plt.text(x=3.5,y=2.8, s="max", size=10)
plt.axhline(y = 0, color = 'black', linewidth=1)
plt.axhline(y = 2, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = -2, color = 'red', linewidth=1, alpha = 0.7)
plt.text(x=0.8,y=2.2, s="2%", size=10, color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=-1.8, s="-2%", color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=0.2, s="0%", color='red', weight ='light', alpha =0.8)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
Between 2011 and 2015, the trends changed:
Percent Change in Exchange Rates (2015 - 2021)
vol_2015_2021 = volatility.copy()[(volatility['Time'].dt.year >=2016)&(volatility['Time'].dt.year <=2021)]
vol_2015_2021.shape
(1284, 7)
v_min_2015_2021_USD= vol_2015_2021['USD/EUR %'].min().round(3)
v_min_2015_2021_GBP = vol_2015_2021['GBP/EUR %'].min().round(3)
v_min_2015_2021_CNY = vol_2015_2021['CNY/EUR %'].min().round(3)
v_max_2015_2021_USD = vol_2015_2021['USD/EUR %'].max().round(3)
v_max_2015_2021_GBP = vol_2015_2021['GBP/EUR %'].max().round(3)
v_max_2015_2021_CNY = vol_2015_2021['CNY/EUR %'].max().round(3)
v_mean_2015_2021_USD = vol_2015_2021['USD/EUR %'].mean().round(3)
v_mean_2015_2021_GBP = vol_2015_2021['GBP/EUR %'].mean().round(3)
v_mean_2015_2021_CNY = vol_2015_2021['CNY/EUR %'].mean().round(3)
fig, ax = plt.subplots(figsize=(8, 5))
fig = plt.title('Percent Change in Exchange Rates (2015 - 2021)', size = 12, weight = 'bold', pad = 42)
plt.suptitle('Comparative analysis of exchange rate volatility,\nas a percentage of daily change' , size = 10)
plt.bar([1, 1.3, 1.6], [v_min_2015_2021_USD, v_mean_2015_2021_USD, v_max_2015_2021_USD], color = 'lightgreen', width = 0.3, label = 'USD/EUR')
plt.bar([2, 2.3, 2.6], [v_min_2015_2021_GBP, v_mean_2015_2021_GBP, v_max_2015_2021_GBP], color = 'royalblue', width = 0.3, label = 'GBP/EUR')
plt.bar([3, 3.3, 3.6], [v_min_2015_2021_CNY, v_mean_2015_2021_CNY, v_max_2015_2021_CNY], color = 'coral', width = 0.3, label = 'CNY/EUR')
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'lower right')
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('% of Daily Change', size=10, weight= 'bold')
plt.text(x=0.9,y=0.1, s="min", size=10)
plt.text(x=1.9,y=0.1, s="min", size=10)
plt.text(x=2.9,y=0.1, s="min", size=10)
plt.text(x=1.2,y=0.1, s="mean", size=10)
plt.text(x=2.2,y=0.1, s="mean", size=10)
plt.text(x=3.2,y=0.1, s="mean", size=10)
plt.text(x=1.5,y=2.5, s="max", size=10)
plt.text(x=2.5,y=5.6, s="max", size=10)
plt.text(x=3.5,y=2.5, s="max", size=10)
plt.axhline(y = 0, color = 'black', linewidth=1)
plt.axhline(y = 2, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = -2, color = 'red', linewidth=1, alpha = 0.7)
plt.axhline(y = 5, color = 'red', linewidth=1, alpha = 0.7)
plt.text(x=0.8,y=5.2, s="5%", size=10, color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=2.2, s="2%", size=10, color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=-1.8, s="-2%", color='red', weight ='light', alpha =0.8)
plt.text(x=0.8,y=0.2, s="0%", color='red', weight ='light', alpha =0.8)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
Between 2015 and 2021, the trends reversed again:
In this last chapter, we will examine the position of the euro in which it found itself at the end of a given time after all its ups and downs. We will use a prepared .csv file containing data for each business day at the end of the every half-year (6/30 and 12/30 or the next business day) from 2000 to 2021.
variability = pd.read_csv('euro-selected_2.csv')
variability['Time'] = pd.to_datetime(variability['Time'])
variability= variability.dropna()
variability.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 43 entries, 0 to 42 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Time 43 non-null datetime64[ns] 1 CNY 43 non-null float64 2 GBP 43 non-null float64 3 USD 43 non-null float64 dtypes: datetime64[ns](1), float64(3) memory usage: 1.7 KB
The Change of USD/EUR Nominal from 1999 to 2021
#function for smothing the graths below
from scipy.signal import savgol_filter
y_filtered_usd = savgol_filter(variability['USD'], 7, 3)
y_filtered_gbp = savgol_filter(variability['GBP'], 7, 3)
y_filtered_cny = savgol_filter(variability['CNY'], 7, 3)
fig, ax = plt.subplots(figsize=(8, 3))
x=variability['Time']
y=variability['USD']
ax.bar(x, y, color ='lightgreen', width =100)
plt.plot(x, y_filtered_usd, color = 'royalblue', linewidth=1, linestyle='dashed')
plt.title('The Change of USD/EUR from 2000 to 2021', fontsize = 12, weight='bold')
plt.xlabel('Years', fontsize=10, weight = 'bold')
plt.ylabel('Exchange Rate, Nominal', size=10, weight= 'bold')
plt.tick_params(left=False)
plt.yticks([])
plt.axhline(y = 1.5, color = 'red', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 1.52, '1.5USD=1EUR', size=10, color='red', weight ='light', alpha =0.8)
plt.axhline(y = 1.0, color = 'red', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 1.02, '1USD=1EUR', size=10, color='red', weight ='light', alpha =0.8)
plt.axhline(y = 0.5, color = 'red', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 0.52, '0.5USD=1EUR', size=10, color='red', weight ='light', alpha =0.8)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
As we can see in the chart above, the USD/EUR exchange rate began its historical path from over 1.2 nominal units, overcame 1.5 for a very short time, and then returned closer to its initial position.
The Change of GBP/EUR Nominal from 2000 to 2021
fig, ax = plt.subplots(figsize=(8, 3))
x=variability['Time']
y=variability['GBP']
ax.bar(x, y, color ='lightblue', width =100)
plt.plot(x, y_filtered_gbp, color = 'darkgreen', linewidth=1, linestyle='dashed')
plt.title('GBP vs EUR from 2000 to 2021', fontsize = 14, weight='bold')
plt.xlabel('Years', fontsize=10, weight = 'bold')
plt.ylabel('Exchange Rate, Nominal', size=10, weight= 'bold')
plt.tick_params(left=False)
plt.yticks([])
plt.axhline(y = 0.5, color = 'red', linewidth=1, alpha= 0.5)
plt.text(dt.date(2000, 1, 10), 0.52, '0.5GBP=1EUR', size=10, color='red', weight ='light', alpha =0.9)
plt.axhline(y = 1, color = 'red', linewidth=1, alpha= 0.7)
plt.text(dt.date(2000, 1, 10), 0.95, '1GBP=1EUR', size=10, color='red', weight ='light', alpha = 0.8)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.show()
As we can see in the chart above, the GBP/EUR exchange rate started its historical journey from about 0.7 conventional units, slowly rose to 0.9 and, after some ups and downs, remained at this position until the beginning of 2021
The Change of CNY/EUR Nominal from 2000 to 2021
fig, ax = plt.subplots(figsize=(8, 3))
x=variability['Time']
y=variability['CNY']
ax.bar(x, y, color ='lightcoral', width =100)
plt.plot(x, y_filtered_cny, color = 'green', linewidth=1, linestyle='dashed')
plt.title('CNY vs EUR from 2000 to 2021', fontsize = 14, weight='bold')
plt.xlabel('Years', fontsize=10, weight = 'bold')
plt.ylabel('Exchange Rate, Nominal', size=10, weight= 'bold')
plt.tick_params(left=False)
plt.yticks([])
plt.axhline(y = 11, color = 'blue', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 11.2, '11CNY=1EUR', size=10, color='blue', weight ='light', alpha =0.8)
plt.axhline(y = 7.0, color = 'blue', linewidth=1, alpha= 0.8)
plt.text(dt.date(2000, 1, 10), 7.02, '7CNY=1EUR', size=10, color='blue', weight ='light')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.ylim(6, 12)
plt.show()
As we can see in the chart above, the CNY/EUR exchange rate began its historical life from over 7 nominal units, overcame 11 units for a very short time, and then returned close to its initial position.
Comparison of Start and End Time Points
To conclude our analysis, let's compare the start and end row of the dataset on nominal value and in percent
fig, ax = plt.subplots(figsize=(6, 3))
x = 0
y1 = volatility[:1]['USD']#2021
y2 = volatility[:1]['GBP']
y3 = volatility[:1]['CNY']
y4 = volatility[-1:]['USD']#2000
y5 = volatility[-1:]['GBP']
y6 = volatility[-1:]['CNY']
ax.bar(x+1, y4, color ='lightgreen', width =0.3, label = 'USD/EUR')
ax.bar(x+1.35, y1, color ='lightgreen', width =0.3)
ax.bar(x+2, y5, color ='lightblue', width =0.3, label = 'GBP/EUR')
ax.bar(x+2.35, y2, color ='lightblue', width =0.3)
ax.bar(x+3, y6, color ='coral', width =0.3, label = 'CNY/EUR')
ax.bar(x+3.35, y3, color ='coral', width =0.3)
fig = plt.title('Comparison of Start and End Time Points', size = 12, weight = 'bold', pad = 30)
plt.suptitle('comparative analysis of the euro exchange rate,\nthe middle of 2000 vs the beginning of 2021' , size = 10)
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('Exchange Rate, Nominal', size=10, weight= 'bold')
plt.text(x=0.9,y=1.3, s="2000", size=10)
plt.text(x=1.25,y=1.4, s='2021', size=10)
plt.text(x=1.9,y=1.1, s="2000", size=10)
plt.text(x=2.25,y=1.3, s="2021", size=10)
plt.text(x=2.9,y=8.6, s="2000", size=10)
plt.text(x=3.25,y=8.2, s="2021", size=10)
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'upper left')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
plt.ylim(0, 10)
plt.show()
The chart above showed the following:
y1 = volatility[:1]['USD']#2021
y2 = volatility[:1]['GBP']
y3 = volatility[:1]['CNY']
y4 = volatility[-1:]['USD']#2000
y5 = volatility[-1:]['GBP']
y6 = volatility[-1:]['CNY']
fig, ax = plt.subplots(figsize=(6, 3))
x = 0
p_usd =round(((100* float(y1)/float(y4))-100), 3)
p_gbp =round(((100* float(y2)/float(y5))-100), 3)
p_cny =round(((100* float(y3)/float(y6))-100), 3)
ax.bar(x+1, p_usd, color ='lightgreen', width =0.3, label = 'USD/EUR')
ax.bar(x+1.4, p_gbp, color ='lightblue', width =0.3, label = 'GBP/EUR')
ax.bar(x+1.8, p_cny, color ='lightcoral', width =0.3, label = 'CNY/EUR')
fig = plt.title('The Change of Euro Values in Percents (2021 to 2000 years)', size = 10, weight = 'bold')
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('Exchange Rate, %', size=10, weight= 'bold')
plt.axhline(y = 0, color = 'black', linewidth=1, alpha = 0.7)
plt.text(x=0.85,y=1, s="0%", color='black', weight ='light', alpha =0.8)
plt.text(x=0.9,y=p_usd - 2, s= p_usd, color='black', weight ='light')
plt.text(x=1.3,y=p_gbp - 2, s= p_gbp, color='black', weight ='light')
plt.text(x=1.75,y=p_cny + 1, s= p_cny, color='black', weight ='light')
plt.text(x=1.05,y=p_usd - 2, s= '%', color='black', weight ='light')
plt.text(x=1.45,y=p_gbp - 2, s= '%', color='black', weight ='light')
plt.text(x=1.85,y=p_cny + 1, s= '%', color='black', weight ='light')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
plt.ylim(-10, 50)
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'upper right')
plt.show()
The chart above showed the following:
Analysis result:
Below we have added a brief analysis of the current situation of the euro compared to its state in 2000 and 2021. The latest values of exchange rates are taken from Currency Converter , on the last update from 19.03.2022.
y1 = volatility[:1]['USD'] #2021
y2 = volatility[:1]['GBP']
y3 = volatility[:1]['CNY']
y4 = volatility[-1:]['USD'] #2000
y5 = volatility[-1:]['GBP']
y6 = volatility[-1:]['CNY']
y7 = 1.107 #USD/EUR 19/03/2022
y8 = 0.840 #GBP/EUR
y9 = 7.042 # CNY/EUR
fig, ax = plt.subplots(figsize=(8, 3))
x = 0
ax.bar(x+1, y4, color ='lightgreen', width =0.25, label = 'USD/EUR')
ax.bar(x+1.26, y1, color ='lightgreen', width =0.25)
ax.bar(x+1.52, y7, color ='lightgreen', width =0.25)
ax.bar(x+2, y5, color ='lightblue', width =0.25, label = 'GBP/EUR')
ax.bar(x+2.26, y2, color ='lightblue', width =0.25)
ax.bar(x+2.52, y8, color ='lightblue', width =0.25)
ax.bar(x+3, y6, color ='lightcoral', width =0.25, label = 'CNY/EUR')
ax.bar(x+3.26, y3, color ='lightcoral', width =0.25)
ax.bar(x+3.52, y9, color ='lightcoral', width =0.25)
fig = plt.title('Comparison of Start and End Time Points', size = 12, weight = 'bold', pad = 30)
plt.suptitle('comparative analysis of the euro exchange rate,\nfrom the middle of 2000 to the current day' , size = 10)
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('Exchange Rate, Nominal', size=10, weight= 'bold')
plt.text(x=0.93,y=1.3, s="2000", size=9)
plt.text(x=1.16,y=1.4, s='2021', size=9)
plt.text(x=1.37,y=1.3, s='19/03/22', size=9)
plt.text(x=1.93,y=1.0, s="2000", size=9)
plt.text(x=2.16,y=1.3, s="2021", size=9)
plt.text(x=2.37,y=1.1, s='19/03/22', size=9)
plt.text(x=2.93,y=8.6, s="2000", size=9)
plt.text(x=3.16,y=8.1, s="2021", size=9)
plt.text(x=3.37,y=7.3, s='19/03/22', size=9)
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'upper left')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
plt.ylim(0, 10)
plt.show()
fig, ax = plt.subplots(figsize=(8, 3))
x = 0
p_usd_21 =round(((100* float(y7)/float(y1))-100), 3) # to 2021
p_gbp_21 =round(((100* float(y8)/float(y2))-100), 3)
p_cny_21 =round(((100* float(y9)/float(y3))-100), 3)
p_usd_20 =round(((100* float(y7)/float(y4))-100), 3) #to 2000
p_gbp_20 =round(((100* float(y8)/float(y5))-100), 3)
p_cny_20 =round(((100* float(y9)/float(y6))-100), 3)
ax.bar(x+1, p_usd_20, color ='lightgreen', width =0.4, label = 'USD/EUR')
ax.bar(x+1.45, p_usd_21, color ='lightgreen', width =0.4)
ax.bar(x+2, p_gbp_20, color ='lightblue', width =0.4, label = 'GBP/EUR')
ax.bar(x+2.45, p_gbp_21, color ='lightblue', width =0.4)
ax.bar(x+3, p_cny_20, color ='lightcoral', width =0.4, label = 'CNY/EUR')
ax.bar(x+3.45, p_cny_21, color ='lightcoral', width =0.4)
plt.legend(fancybox=True, framealpha = 1, borderpad = 1, shadow = True, loc = 'upper right')
fig = plt.title('The Change of Euro Values in Percents\n (19/03/2022 to 2021 & 2000 years)', size = 10, weight = 'bold')
plt.tick_params(left=False)
plt.xticks([])
plt.yticks([])
plt.ylabel('Exchange Rate, %', size=10, weight= 'bold')
plt.axhline(y = 0, color = 'black', linewidth=1, alpha = 0.7)
plt.text(x=0.8,y=1, s="0%", color='black', weight ='light', alpha =0.8)
plt.text(x=0.8,y=-3, s="% to 2000", size=8, color='black', weight ='light', alpha =0.8)
plt.text(x=1.25,y=2, s="% to 2021", size=8, color='black', weight ='light', alpha =0.8)
plt.text(x=1.8,y=-3, s="% to 2000", size= 8, color='black', weight ='light', alpha =0.8)
plt.text(x=2.25,y=2, s="% to 2021", size=8, color='black', weight ='light', alpha =0.8)
plt.text(x=2.8,y=-3, s="% to 2000", size=8, color='black', weight ='light', alpha =0.8)
plt.text(x=3.25,y=2, s="% to 2021", size=8, color='black', weight ='light', alpha =0.8)
plt.text(x=0.85,y=p_usd_20 + 2, s= p_usd_20, color='black', weight ='light')
plt.text(x=1.85,y=p_gbp_20 + 2, s= p_gbp_20, color='black', weight ='light')
plt.text(x=2.85,y=p_cny_20 - 4, s= p_cny_20, color='black', weight ='light')
plt.text(x=1.3,y=p_usd_21-4, s= p_usd_21, color='black', weight ='light')
plt.text(x=2.3,y=p_gbp_21-4, s= p_gbp_21, color='black', weight ='light')
plt.text(x=3.3,y=p_cny_21 - 4, s= p_cny_21, color='black', weight ='light')
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
plt.ylim(-25, 45)
plt.show()
The charts above showed the following: