<jupyter_start><jupyter_text>Nasdaq Composite Trading AbstractThe Nasdaq Stock Market is an American stock exchange based in New York City. It is ranked second on the list of stock exchanges by market capitalization of shares traded, behind the New York Stock Exchange. The exchange platform is owned by Nasdaq, Inc., which also owns the Nasdaq Nordic stock market network and several U.S. stock and options exchanges.The Nasdaq Composite (IXIC) is a stock market index that includes almost all stocks listed on the Nasdaq stock exchange. Along with the Dow Jones Industrial Average and S&P 500, it is one of the three most-followed stock market indices in the United States. The composition of the NASDAQ Composite is heavily weighted towards companies in the information technology sector. The Nasdaq-100, which includes 100 of the largest non-financial companies in the Nasdaq Composite, accounts for over 90% of the movement of the Nasdaq Composite.  Load the Data<jupyter_code>import math
import numpy as np 
import pandas as pd 
import yfinance as yf
import seaborn as sns
import matplotlib.pyplot as plt 
import matplotlib.dates as mdates # Formatting dates

#from keras.optimizers import Adam # For detailed configuration of the optimizer *****
from keras.models import Sequential # Deep learning library, used for neural networks
from keras.callbacks import EarlyStopping # EarlyStopping during model training
from keras.layers import LSTM, Dense, Dropout # Deep learning classes for recurrent and regular densely-connected layers
from sklearn.preprocessing import RobustScaler # This Scaler removes the median and scales the data according to the quantile range to normalize the price data 
from datetime import date, timedelta, datetime
from pandas.plotting import register_matplotlib_converters # This function adds plotting functions for calender dates
from sklearn.metrics import mean_absolute_error, mean_squared_error

today = date.today()
date_today = today.strftime("%Y-%m-%d")                      
date_start = '2000-01-01'

stockname = 'NASDAQ'
symbol = '^IXIC'                                             
df = yf.download(symbol, start=date_start, end=date_today)
df<jupyter_output>[*********************100%***********************]  1 of 1 completed<jupyter_text>PreProcessing<jupyter_code>df.isna().sum()
df.info()
train_df = df.sort_values(by=['Date']).copy()     


date_index = train_df.index                       
date_index_df = pd.DataFrame(date_index) 

train_df.reset_index(inplace=True)                
train_df
print('Any missing value ?',train_df.isnull().values.any())   
train_df.info()
train_df.describe()<jupyter_output><empty_output><jupyter_text>EDA<jupyter_code>df_plot = df.copy()

list_length = df_plot.shape[1]
ncols = 2
nrows = int(round(list_length / ncols, 0))

fig, ax = plt.subplots(nrows=nrows, ncols=ncols, sharex=True, figsize=(14, 7))
fig.subplots_adjust(hspace=0.5, wspace=0.5)
for i in range(0, list_length):
        ax = plt.subplot(nrows,ncols,i+1)
        sns.lineplot(data = df_plot.iloc[:, i], ax=ax)                             # Plot lineplots
        ax.set_title(df_plot.columns[i])
        ax.tick_params(axis="x", rotation=30, labelsize=10, length=0)
        ax.xaxis.set_major_locator(mdates.AutoDateLocator())
fig.tight_layout()
plt.show()
sns.set_style("darkgrid")
sns.boxplot(x = df_plot['Volume']) 
plt.show()
x = train_df['Date'].values
y1 = train_df['Open'].values

fig, ax = plt.subplots(1, 1, figsize=(16,5), dpi= 120)
plt.fill_between(x, y1=y1, y2=-y1, alpha=0.5, linewidth=2, color='red')   #Since all values are positive, you can show this on both sides of the Y axis to emphasize the growth.
plt.ylim(-20000, 20000)
plt.title('Open (Two Side View)', fontsize=16)
plt.hlines(y=0, xmin=np.min(train_df.Date), xmax=np.max(train_df.Date), linewidth=.5)
plt.show()
x = train_df['Date'].values
y1 = train_df['Close'].values

fig, ax = plt.subplots(1, 1, figsize=(16,5), dpi= 120)
plt.fill_between(x, y1=y1, y2=-y1, alpha=0.5, linewidth=2, color='seagreen')
plt.ylim(-20000, 20000)
plt.title('Close (Two Side View)', fontsize=16)
plt.hlines(y=0, xmin=np.min(train_df.Date), xmax=np.max(train_df.Date), linewidth=.5)
plt.show()
sns.set_theme(style="darkgrid")
plt.figure(figsize=(12,8))
sns.lineplot(x="Date",y="High",data=train_df,linewidth=10.0,label='high')
sns.lineplot(x="Date",y="Low",data=train_df,linewidth=3.0,label='Low')
plt.xlabel('Date',fontsize=15.0)
plt.ylabel('Price',fontsize=15.0)
plt.title('Nasdaq Composite \nDate vs Price',fontsize=20.0)
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Feature Engineering<jupyter_code>d = pd.to_datetime(train_df.index)
train_df['Day'] = d.strftime("%d")      
train_df['Month'] = d.strftime("%m") 
train_df['Year'] = d.strftime("%Y") 
train_df
def createFeatures(df):
    df = pd.DataFrame(df)

    
    df['Close_Diff'] = df['Adj Close'].diff()
        
    
    df['MA200'] = df['Close'].rolling(window=200).mean() 
    df['MA100'] = df['Close'].rolling(window=100).mean() 
    df['MA50'] = df['Close'].rolling(window=50).mean() 
    df['MA26'] = df['Close'].rolling(window=26).mean()            # Moving averages - different periods
    df['MA20'] = df['Close'].rolling(window=20).mean() 
    df['MA12'] = df['Close'].rolling(window=12).mean() 
    
    
    df['DIFF-MA200-MA50'] = df['MA200'] - df['MA50']
    df['DIFF-MA200-MA100'] = df['MA200'] - df['MA100']
    df['DIFF-MA200-CLOSE'] = df['MA200'] - df['Close']            # SMA Differences - different periods
    df['DIFF-MA100-CLOSE'] = df['MA100'] - df['Close']
    df['DIFF-MA50-CLOSE'] = df['MA50'] - df['Close']
    
    
    df['MA200_low'] = df['Low'].rolling(window=200).min()
    df['MA14_low'] = df['Low'].rolling(window=14).min()
    df['MA200_high'] = df['High'].rolling(window=200).max()       # Moving Averages on high, lows, and std - different periods
    df['MA14_high'] = df['High'].rolling(window=14).max()
    df['MA20dSTD'] = df['Close'].rolling(window=20).std() 
    
   
    df['EMA12'] = df['Close'].ewm(span=12, adjust=False).mean()
    df['EMA20'] = df['Close'].ewm(span=20, adjust=False).mean()
    df['EMA26'] = df['Close'].ewm(span=26, adjust=False).mean()   # Exponential Moving Averages (EMAS) - different periods
    df['EMA100'] = df['Close'].ewm(span=100, adjust=False).mean()
    df['EMA200'] = df['Close'].ewm(span=200, adjust=False).mean()

    
    df['close_shift-1'] = df.shift(-1)['Close']
    df['close_shift-2'] = df.shift(-2)['Close']                   # Shifts (one day before and two days before)

    
    df['Bollinger_Upper'] = df['MA20'] + (df['MA20dSTD'] * 2)    
    df['Bollinger_Lower'] = df['MA20'] - (df['MA20dSTD'] * 2)     # Bollinger Bands
    
    
    df['K-ratio'] = 100*((df['Close'] - df['MA14_low']) / (df['MA14_high'] - df['MA14_low']) )
    df['RSI'] = df['K-ratio'].rolling(window=3).mean()            # Relative Strength Index (RSI)
 
    
    df['MACD'] = df['EMA12'] - df['EMA26']                        # Moving Average Convergence/Divergence (MACD)
    
    
    nareplace = df.at[df.index.max(), 'Close']                    # Replace NA's 
    df.fillna((nareplace), inplace=True)
    
    return df
FEATURES = [
#             'High',
#             'Low',
#             'Open',
              'Close',
#             'Volume',
              'Date',
#             'Day',
#             'Month',
#             'Year',
#             'Adj Close',
#             'close_shift-1',
#             'close_shift-2',
              'MACD',
              'RSI',
#             'MA200',
#             'MA200_high',
#             'MA200_low',
              'Bollinger_Upper',                                      # List of considered Features
              'Bollinger_Lower',
#             'MA100',            
#             'MA50',
#             'MA26',
#             'MA14_low',
#             'MA14_high',
#             'MA12',
#             'EMA20',
#             'EMA100',
#             'EMA200',
#             'DIFF-MA200-MA50',
#             'DIFF-MA200-MA10',
#             'DIFF-MA200-CLOSE',
#             'DIFF-MA100-CLOSE',
#             'DIFF-MA50-CLOSE'
           ]<jupyter_output><empty_output><jupyter_text>Short Term Analysis<jupyter_code>data = createFeatures(train_df)                               # Dataset with features

use_start_date = pd.to_datetime("2020-01-01" )
data = data[data['Date'] > use_start_date].copy()             # Shift the timeframe

data_filtered = data[FEATURES]                                # Filter the data to the list of FEATURES


data_filtered_ext = data_filtered.copy()
data_filtered_ext['Prediction'] = data_filtered_ext['Close']  # We add a prediction column and set dummy values to prepare the data for scaling
print(data_filtered_ext.tail().to_string())

dfs = data_filtered_ext.copy()
del dfs[('Date')]                                             # remove Date column before training 
del dfs[('Prediction')]

# Register matplotlib converters
register_matplotlib_converters()

nrows = dfs.shape[1]
fig, ax = plt.subplots(figsize=(16, 8))                       # Plot parameters
x = data_filtered_ext['Date'] 
assetname_list = []

for i in range(nrows):
    assetname = dfs.columns[i-1]
    y = data_filtered_ext[assetname]
    ax.plot(x, y, label=assetname, linewidth=1.0)             # Plotting each column
    assetname_list.append(assetname)

# Configure and show the plot    
ax.set_title(stockname + ' 2020-2021 price chart')
ax.legend()
ax.tick_params(axis="x", rotation=90, labelsize=10, length=0)   
plt.show<jupyter_output>Close       Date       MACD        RSI  Bollinger_Upper  Bollinger_Lower    Prediction
5516  15381.320312 2021-12-02  31.162609  11.385320     16225.724148     15343.461985  15381.320312
5517  15085.469727 2021-12-03 -14.349003  11.621804     16275.423396     15208.278753  15085.469727
5518  15225.150391 2021-12-06 -38.700110  18.925039     16273.676822     15135.381381  15225.150391
5519  15686.919922 2021-12-07 -20.501271  31.334912     16243.674989     15135.839172  15686.919922
5520  15786.990234 2021-12-08   1.973529  49.586979     16233.012009     15136.547171  15786.990234<jupyter_text>Long Term Analysis<jupyter_code>data = createFeatures(train_df)                               # Dataset with features

use_start_date = pd.to_datetime("2001-01-01" )
data = data[data['Date'] > use_start_date].copy()             # Shift the timeframe

data_filtered = data[FEATURES]                                # Filter the data to the list of FEATURES


data_filtered_ext = data_filtered.copy()
data_filtered_ext['Prediction'] = data_filtered_ext['Close']  # We add a prediction column and set dummy values to prepare the data for scaling
print(data_filtered_ext.tail().to_string())

dfs = data_filtered_ext.copy()
del dfs[('Date')]                                             # remove Date column before training 
del dfs[('Prediction')]

# Register matplotlib converters
register_matplotlib_converters()

nrows = dfs.shape[1]
fig, ax = plt.subplots(figsize=(16, 8))                       # Plot parameters
x = data_filtered_ext['Date'] 
assetname_list = []

for i in range(nrows):
    assetname = dfs.columns[i-1]
    y = data_filtered_ext[assetname]
    ax.plot(x, y, label=assetname, linewidth=1.0)             # Plotting each column
    assetname_list.append(assetname)

# Configure and show the plot    
ax.set_title(stockname + ' 2020-2021 price chart')
ax.legend()
ax.tick_params(axis="x", rotation=90, labelsize=10, length=0)   
plt.show<jupyter_output>Close       Date       MACD        RSI  Bollinger_Upper  Bollinger_Lower    Prediction
5516  15381.320312 2021-12-02  31.162609  11.385320     16225.724148     15343.461985  15381.320312
5517  15085.469727 2021-12-03 -14.349003  11.621804     16275.423396     15208.278753  15085.469727
5518  15225.150391 2021-12-06 -38.700110  18.925039     16273.676822     15135.381381  15225.150391
5519  15686.919922 2021-12-07 -20.501271  31.334912     16243.674989     15135.839172  15686.919922
5520  15786.990234 2021-12-08   1.973529  49.586979     16233.012009     15136.547171  15786.990234<jupyter_text>Hypothesis Testing<jupyter_code>df_h = df.copy()
df_h = df_h.reset_index()
df_h
plt.plot(df['Volume'])
plt.title('Volume vs Year')
plt.xlabel('Year')
plt.ylabel('Volume')
h1 = df_h['Volume'].values
import random
values =(random.sample(list(h1), 500))
values
average = round(sum(values)/len(values))
average
h0 = round(df_h['Volume'].mean())
h0<jupyter_output><empty_output><jupyter_text>Null hypothesis: Average volume traded in day is 2158116573Alternate hypothesis: Average volume traded in day > 2158116573<jupyter_code>import scipy.stats
import statistics
sample_cured=values
alpha=0.1
z_critical=scipy.stats.norm.ppf(1-alpha)
Mu=statistics.mean(h1)
xbar=statistics.mean(sample_cured)
n=len(values)
std=h1.std()
z=(xbar-Mu)/(std/np.sqrt(n))
print(z," ",z_critical)
if(z<z_critical):
    print("Null Hyothesis Accepted")
else:
    print("Alternate hypothesis accepted")
h2 = df_h[pd.DatetimeIndex(df_h['Date']).year == 2020]['Close'].values
h2
h2_values =(random.sample(list(h2), 100))
average = round(sum(h2_values)/len(h2_values))
average
h0 = statistics.mean(h2)
h0<jupyter_output><empty_output><jupyter_text>Null hypothesis: Average trading volume in 2020 is 10201Alternate hypothesis : Average trading volume in 2020<jupyter_code>import scipy.stats
import statistics
sample_cured=h2_values
alpha=0.1
z_critical=scipy.stats.norm.ppf(1-alpha)
Mu=statistics.mean(h2)
xbar=statistics.mean(sample_cured)
n=len(h2_values)
std=h2.std()
z=(xbar-Mu)/(std/np.sqrt(n))
print(z," ",z_critical)
if(z<z_critical):
    print("Null Hyothesis Accepted")
else:
    print("Alternate hypothesis accepted")<jupyter_output>-0.07019620382380337   1.2815515655446004
Null Hyothesis Accepted<jupyter_text>Scaling and Transforming the Data<jupyter_code>nrows = dfs.shape[0]
np_data_unscaled = np.reshape(np.array(dfs), (nrows, -1))
print(np_data_unscaled.shape)

scaler = RobustScaler()
np_data = scaler.fit_transform(np_data_unscaled)

scaler_pred = RobustScaler()
df_Close = pd.DataFrame(data_filtered_ext['Close'])
np_Close_scaled = scaler_pred.fit_transform(df_Close)
sequence_length = 50

train_data_length = math.ceil(np_Close_scaled.shape[0] * 0.8)

# Create the training and test data
train_data = np_Close_scaled[0:train_data_length, :]
test_data = np_Close_scaled[train_data_length - sequence_length:, :]

def partition_dataset(sequence_length, data):
    x, y = [], []
    data_len = data.shape[0]

    for i in range(sequence_length, data_len):
        x.append(data[i-sequence_length:i,:]) 
        y.append(data[i, 0]) 
    
    x = np.array(x)
    y = np.array(y)
    return x, y

x_train, y_train = partition_dataset(sequence_length, train_data)
x_test, y_test = partition_dataset(sequence_length, test_data)


print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)

print(x_train[1][sequence_length-1][0])
print(y_train[0])<jupyter_output>(4165, 50, 1) (4165,)
(1053, 50, 1) (1053,)
-0.2527193861022734
-0.2527193861022734<jupyter_text>Model Training<jupyter_code>model = Sequential()

n_neurons = x_train.shape[1] * x_train.shape[2]
print('timesteps: ' + str(x_train.shape[1]) + ',' + ' features:' + str(x_train.shape[2]))
model.add(LSTM(n_neurons, return_sequences=True, input_shape=(x_train.shape[1], x_train.shape[2]))) 

model.add(LSTM(n_neurons, return_sequences=True))

model.add(LSTM(n_neurons, return_sequences=False))
model.add(Dense(32))
model.add(Dense(1, activation='relu'))
 
optimizer='adam'; loss='mean_squared_error'; epochs = 100; batch_size = 32; patience = 6;

parameter_list = ['epochs ' + str(epochs), 'batch_size ' + str(batch_size), 'patience ' + str(patience), 'optimizer ' + str(optimizer), 'loss ' + str(loss)]
print('Parameters: ' + str(parameter_list))


model.compile(optimizer=optimizer, loss=loss)
early_stop = EarlyStopping(monitor='loss', patience=patience, verbose=1)
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, callbacks=[early_stop], shuffle = True,
                  validation_data=(x_test, y_test))


fig, ax = plt.subplots(figsize=(6, 6), sharex=True)
plt.plot(history.history["loss"])
plt.title("Model loss")
plt.ylabel("Loss")
plt.xlabel("Epoch")
ax.xaxis.set_major_locator(plt.MaxNLocator(epochs))
plt.legend(["Train", "Test"], loc="upper left")
plt.grid()
plt.show()
model.summary()<jupyter_output>Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 lstm (LSTM)                 (None, 50, 50)            10400     
                                                                 
 lstm_1 (LSTM)               (None, 50, 50)            20200     
                                                                 
 lstm_2 (LSTM)               (None, 50)                20200     
                                                                 
 dense (Dense)               (None, 32)                1632      
                                                                 
 dense_1 (Dense)             (None, 1)                 33        
                                                                 
=================================================================
Total params: 52,465
Trainable params: 52,465
Non-traina[...]<jupyter_text>Model Performance<jupyter_code>y_pred_scaled = model.predict(x_test)

# Unscale the predicted values
y_pred = scaler_pred.inverse_transform(y_pred_scaled)
y_test_unscaled = scaler_pred.inverse_transform(y_test.reshape(-1, 1))
y_test_unscaled.shape

MAE = mean_absolute_error(y_test_unscaled, y_pred)
print(f'Median Absolute Error (MAE): {np.round(MAE, 2)}')

MAPE = np.mean((np.abs(np.subtract(y_test_unscaled, y_pred)/ y_test_unscaled))) * 100
print(f'Mean Absolute Percentage Error (MAPE): {np.round(MAPE, 2)} %')

MDAPE = np.median((np.abs(np.subtract(y_test_unscaled, y_pred)/ y_test_unscaled)) ) * 100
print(f'Median Absolute Percentage Error (MDAPE): {np.round(MDAPE, 2)} %')

display_start_date = "2015-01-01" 

data_filtered_sub = data_filtered.copy()

date_index = date_index_df[date_index_df['Date'] > use_start_date].copy()
data_filtered_sub['Date'] = date_index

train = data_filtered_sub[:train_data_length + 1]
valid = data_filtered_sub[train_data_length:]
valid.insert(1, "Predictions", y_pred, True)
valid.insert(1, "Difference", valid["Predictions"] - valid["Close"], True)


valid = valid[valid['Date'] > display_start_date]
train = train[train['Date'] > display_start_date]

fig, ax = plt.subplots(figsize=(16, 8), sharex=True)

plt.title("Predictions vs Ground Truth", fontsize=20)
plt.ylabel(stockname, fontsize=18)
plt.plot(train["Close"], color="#039dfc", linewidth=1.0)
plt.plot(valid["Predictions"], color="#E91D9E", linewidth=1.0)
plt.plot(valid["Close"], color="black", linewidth=1.0)
plt.legend(["Train", "Test Predictions", "Ground Truth"], loc="upper left")

valid.loc[valid["Difference"] >= 0, 'diff_color'] = "#2BC97A"
valid.loc[valid["Difference"] < 0, 'diff_color'] = "#C92B2B"
plt.bar(valid.index, valid["Difference"], width=0.8, color=valid['diff_color'])

plt.show()<jupyter_output>Median Absolute Error (MAE): 567.81
Mean Absolute Percentage Error (MAPE): 4.42 %
Median Absolute Percentage Error (MDAPE): 1.57 %<jupyter_text>Trade Trend Prediction (Gradient Boosting)<jupyter_code>df = df.reset_index()
df = df[df['Date'] >= '2012-01-01']
df.set_index('Date', inplace = True)
df
df = df.reset_index()
df
df
# Normalize aclose value
# We use this value to train model

df['return'] = df['Adj Close'] - df['Adj Close'].shift(1)
return_range = df['return'].max() - df['return'].min()
df['return'] = df['return'] / return_range

df.plot(x='Date', y='return', figsize=(10,4))
# Make label, 1 as rising price, 0 as falling price

df['label'] = df['return'].shift(-1)
df['label'] = df['label'].apply(lambda x: 1 if x>0.0 else 0)
# df.dropna(inplace=True)
df.tail()
df1 = df[df['label'] == 1]
df2 = df[df['label'] == 0]
print('df1 ',df1.shape)
print('df2 ',df2.shape)
df1 =df1.sample(n=1088)
df1
df_merge = pd.concat([df1, df2])
df_merge
df_merge = df_merge.sort_values("Date")
df_merge
df_merge.isna().sum()
df_merge.drop(index=df_merge.index[0], axis=0,inplace=True)
df_merge.isna().sum()
df_merge.set_index('Date',inplace = True)
df_merge.reset_index(inplace = True)
df_merge
# Make training dataset

n_features = 60 # number of features or taking last 60 days for each  tree

train_x = np.array([]).reshape([-1,n_features]) #empty array of size 60
train_y = np.array([]).reshape([-1,1])
for index, row in df_merge.iterrows():
    i = df_merge.index.get_loc(index)  #index
    if i<n_features:
        continue
    
    _x = np.array(df[i-n_features+1:i+1]['return']).T.reshape([1, -1]) #taking 60 entries
    _y = df_merge.loc[i]['label']
    train_x = np.vstack((train_x, _x))    #vertical stacking
    train_y = np.vstack((train_y, _y))
train_y = train_y.reshape([-1])
print(train_x.shape)
print(train_y.shape)
print('%% of Class0 : %f' % (np.count_nonzero(train_y == 0)/float(len(train_y))))
print('%% of Class1 : %f' % (np.count_nonzero(train_y == 1)/float(len(train_y))))
from sklearn.ensemble import GradientBoostingClassifier
from sklearn import metrics
acc_score = []
n_estimators = [1, 2, 4, 8, 16, 32, 64, 100, 200, 400, 800, 1600, 3200, 6000, 8000, 10000, 12000]
for i in n_estimators:
    clf = GradientBoostingClassifier(n_estimators=i, random_state=0)
    train_len = int(len(train_x)*0.95)
    clf.fit(train_x[:train_len], train_y[:train_len])

    predicted_values = clf.predict(train_x[train_len:])

    x = metrics.accuracy_score(train_y[train_len:], predicted_values)
    acc_score.append(x) 
    
plt.plot(n_estimators, acc_score, 'b', label='Accuracy')
plt.ylabel('Accuracy score')
plt.xlabel('n_estimators')
plt.show()
# Define Model and fit
# Here we use 95% of data for training, and last 5% for testing

from sklearn.ensemble import GradientBoostingClassifier
clf = GradientBoostingClassifier(random_state=0, n_estimators=4)

train_len = int(len(train_x)*0.95)
clf.fit(train_x[:train_len], train_y[:train_len])

accuracy = clf.score(train_x[train_len:], train_y[train_len:])
print('Testing Accuracy: %f' % accuracy)
# Predict test data

pred = clf.predict(train_x[train_len:])


# Calculate equity..

contracts  = 10000.0
commission = 0.0


df_trade = pd.DataFrame(train_x[train_len:,-1], columns=['return'])
df_trade['label']  = train_y[train_len:]
df_trade['pred']   = pred
df_trade['won']    = df_trade['label'] == df_trade['pred']          #comparing prediction and actual
df_trade['return'] = df_trade['return'].shift(-1) * return_range
df_trade.drop(df_trade.index[len(df_trade)-1], inplace=True)

def calc_profit(row):
    if row['won']:
        return abs(row['return'])*contracts - commission       #net p&l for all the contracts
    else:
        return -abs(row['return'])*contracts - commission

df_trade['pnl'] = df_trade.apply(lambda row: calc_profit(row), axis=1)
df_trade['equity'] = df_trade['pnl'].cumsum()

display(df_trade.tail())
df_trade.plot(y='equity', figsize=(10,4), title='Backtest with $10000 initial capital')
plt.xlabel('Trades')
plt.ylabel('Equity (USD)')
for r in df_trade.iterrows():
    if r[1]['won']:
        plt.axvline(x=r[0], linewidth=0.5, alpha=0.8, color='g')
    else:
        plt.axvline(x=r[0], linewidth=0.5, alpha=0.8, color='r')

# Calculate summary of trades

n_win_trades = float(df_trade[df_trade['pnl']>0.0]['pnl'].count())
n_los_trades = float(df_trade[df_trade['pnl']<0.0]['pnl'].count())
print("Number Winning Trades : %d" % n_win_trades)
print("Number Losing Trades  : %d" % n_los_trades)
print("Percent Profitable    : %.2f%%" % (100*n_win_trades/(n_win_trades + n_los_trades)))
print("Avg Win Trade         : $%.3f" % df_trade[df_trade['pnl']>0.0]['pnl'].mean())
print("Avg Los Trade         : $%.3f" % df_trade[df_trade['pnl']<0.0]['pnl'].mean())
print("Largest Win Trade     : $%.3f" % df_trade[df_trade['pnl']>0.0]['pnl'].max())
print("Largest Los Trade     : $%.3f" % df_trade[df_trade['pnl']<0.0]['pnl'].min())
print("Profit Factor         : %.2f" % abs(df_trade[df_trade['pnl']>0.0]['pnl'].sum()/df_trade[df_trade['pnl']<0.0]['pnl'].sum()))

df_trade['pnl'].hist(bins=20)
from sklearn.metrics import classification_report
print(classification_report(train_y[train_len:], pred))<jupyter_output>precision    recall  f1-score   support

         0.0       0.47      0.51      0.49        47
         1.0       0.58      0.54      0.56        59

    accuracy                           0.53       106
   macro avg       0.53      0.53      0.53       106
weighted avg       0.53      0.53      0.53       106
StarcoderdataJupyterStructuredCleanDedup