BNB price analysis
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
df = pd.read_csv('BNB-USD.csv')
df.head()
Date | Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|---|
0 | 2017-11-09 | 2.05314 | 2.17423 | 1.89394 | 1.99077 | 1.99077 | 19192200.0 |
1 | 2017-11-10 | 2.00773 | 2.06947 | 1.64478 | 1.79684 | 1.79684 | 11155000.0 |
2 | 2017-11-11 | 1.78628 | 1.91775 | 1.61429 | 1.67047 | 1.67047 | 8178150.0 |
3 | 2017-11-12 | 1.66889 | 1.67280 | 1.46256 | 1.51969 | 1.51969 | 15298700.0 |
4 | 2017-11-13 | 1.52601 | 1.73502 | 1.51760 | 1.68662 | 1.68662 | 12238800.0 |
df.tail()
Date | Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|---|
2028 | 2023-05-30 | 311.810333 | 314.276611 | 311.313507 | 311.684509 | 311.684509 | 392038878.0 |
2029 | 2023-05-31 | 311.695709 | 311.846649 | 305.376404 | 306.866699 | 306.866699 | 474410245.0 |
2030 | 2023-06-01 | 306.882813 | 307.613770 | 303.644562 | 304.953278 | 304.953278 | 354897855.0 |
2031 | 2023-06-02 | NaN | NaN | NaN | NaN | NaN | NaN |
2032 | 2023-06-03 | 307.370331 | 307.370331 | 307.334808 | 307.334808 | 307.334808 | 380250496.0 |
df.describe()
Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|
count | 2032.000000 | 2032.000000 | 2032.000000 | 2032.000000 | 2032.000000 | 2.032000e+03 |
mean | 158.956768 | 163.860205 | 153.668686 | 159.075751 | 159.075751 | 9.367168e+08 |
std | 181.151077 | 186.767035 | 174.910847 | 181.076968 | 181.076968 | 1.384815e+09 |
min | 1.511360 | 1.582660 | 1.462560 | 1.510360 | 1.510360 | 9.284000e+03 |
25% | 14.691567 | 15.289252 | 14.206488 | 14.794200 | 14.794200 | 1.561682e+08 |
50% | 28.723639 | 29.370382 | 27.973465 | 28.788359 | 28.788359 | 3.960007e+08 |
75% | 307.606750 | 313.983650 | 300.660980 | 307.617782 | 307.617782 | 1.289710e+09 |
max | 676.315918 | 690.931946 | 634.549500 | 675.684082 | 675.684082 | 1.798295e+10 |
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2033 entries, 0 to 2032
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Date 2033 non-null object
1 Open 2032 non-null float64
2 High 2032 non-null float64
3 Low 2032 non-null float64
4 Close 2032 non-null float64
5 Adj Close 2032 non-null float64
6 Volume 2032 non-null float64
dtypes: float64(6), object(1)
memory usage: 111.3+ KB
# find null values
df.isnull().sum()
Date 0
Open 1
High 1
Low 1
Close 1
Adj Close 1
Volume 1
dtype: int64
#find duplicate values
df.duplicated().sum()
0
df = df.dropna()
df['Date']= pd.to_datetime(df['Date'])
df.set_index('Date', inplace=True)
df['diff'] = df['Open'] - df['Close']
plt.figure(figsize=(14,10))
plt.plot(df['Close'])
plt.grid()
plt.xlabel('Year')
plt.ylabel('Close Price')
plt.title('BNB Price')
plt.show()
Daily close
daily_close = df[['Adj Close']]
daily_pct_c = daily_close.pct_change()
daily_pct_c.fillna(0, inplace=True)
print(daily_pct_c)
Adj Close
Date
2017-11-09 0.000000
2017-11-10 -0.097415
2017-11-11 -0.070329
2017-11-12 -0.090262
2017-11-13 0.109845
... ...
2023-05-29 -0.007837
2023-05-30 -0.000393
2023-05-31 -0.015457
2023-06-01 -0.006235
2023-06-03 0.007809
[2032 rows x 1 columns]
daily_pct_c.hist(bins=50)
plt.show()
print(daily_pct_c.describe())
Adj Close
count 2032.000000
mean 0.004119
std 0.058566
min -0.419046
25% -0.020580
50% 0.001015
75% 0.026164
max 0.697604
pd.plotting.scatter_matrix(daily_pct_c, diagonal='kde', alpha=0.1,figsize=(8,8))
plt.show()
Moving Average
adj_close_px = df['Adj Close']
df['50'] = adj_close_px.rolling(window=50).mean()
df['100'] = adj_close_px.rolling(window=100).mean()
plt.figure(figsize=(16,12))
plt.plot(df['Adj Close'], label='Adj Close')
plt.plot(df['50'], label='50')
plt.plot(df['100'], label='100')
plt.title('Simple Moving Average', fontsize=20)
plt.grid()
plt.legend()
plt.figure(figsize=(16,12))
plt.plot(adj_close_px, label='Adj Close')
plt.plot(adj_close_px.ewm(span=50, adjust=False).mean(), label='50')
plt.plot(adj_close_px.ewm(span=100, adjust=False).mean(), label='100')
plt.title('Exponential Moving Average', fontsize=20)
plt.legend()
plt.grid()
plt.show()
Volatility Calculation
min_periods = 75
vol = daily_pct_c.rolling(min_periods).std() * np.sqrt(min_periods)
plt.figure(figsize=(10, 8))
plt.plot(vol)
plt.title('Volatility of BNB')
plt.show()
Trading strategy
Moving Average Crossover
short_window = 13
long_window = 49
signals = pd.DataFrame(index=df.index)
signals['signal'] = 0.0
signals['short_mavg'] = df['Close'].rolling(window=short_window, min_periods=1, center=False).mean()
signals['long_mavg'] = df['Close'].rolling(window=long_window, min_periods=1, center=False).mean()
signals['signal'][short_window:] = np.where(signals['short_mavg'][short_window:]
> signals['long_mavg'][short_window:], 1.0, 0.0)
signals['positions'] = signals['signal'].diff()
fig = plt.figure(figsize=(14,10))
ax1 = fig.add_subplot(111, ylabel='Price ($)')
df['Close'].plot(ax=ax1, lw=2.)
signals[['short_mavg', 'long_mavg']].plot(ax=ax1, lw=2.)
ax1.plot(signals.loc[signals.positions == 1.0].index,
signals.short_mavg[signals.positions == 1.0],
'^', markersize=10, color='red')
ax1.plot(signals.loc[signals.positions == -1.0].index,
signals.short_mavg[signals.positions == -1.0],
'v', markersize=10, color='black')
plt.show()
Backtesting
initial_capital= float(100000.0)
positions = pd.DataFrame(index=signals.index).fillna(0.0)
positions['BNB'] = 100*signals['signal']
portfolio = positions.multiply(df['Adj Close'], axis=0)
pos_diff = positions.diff()
portfolio['holdings'] = (positions.multiply(df['Adj Close'], axis=0)).sum(axis=1)
portfolio['cash'] = initial_capital - (pos_diff.multiply(df['Adj Close'], axis=0)).sum(axis=1).cumsum()
portfolio['total'] = portfolio['cash'] + portfolio['holdings']
portfolio['returns'] = portfolio['total'].pct_change()
portfolio.head()
Date | BNB | holdings | cash | total | returns |
---|---|---|---|---|---|
2017-11-09 | 0.0 | 0.0 | 100000.0 | 100000.0 | NaN |
2017-11-10 | 0.0 | 0.0 | 100000.0 | 100000.0 | 0.0 |
2017-11-11 | 0.0 | 0.0 | 100000.0 | 100000.0 | 0.0 |
2017-11-12 | 0.0 | 0.0 | 100000.0 | 100000.0 | 0.0 |
2017-11-13 | 0.0 | 0.0 | 100000.0 | 100000.0 | 0.0 |
fig = plt.figure(figsize=(14,10))
ax1 = fig.add_subplot(111, ylabel='Portfolio value in $')
portfolio['total'].plot(ax=ax1, lw=2.)
ax1.plot(portfolio.loc[signals.positions == 1.0].index,
portfolio.total[signals.positions == 1.0],
'^', markersize=10, color='m')
ax1.plot(portfolio.loc[signals.positions == -1.0].index,
portfolio.total[signals.positions == -1.0],
'v', markersize=10, color='k')
plt.title('Portfolio Value in Time')
plt.show()
The full example is on my Kaggle account. This is the link.
https://www.kaggle.com/code/mixmore/bnb-price-analysis
This is just an explanation of the example on Kaggle.