Overall Statistics
Total Orders
6532
Average Win
2.49%
Average Loss
-1.08%
Compounding Annual Return
680.195%
Drawdown
99.300%
Expectancy
0.419
Start Equity
1000000.00
End Equity
259614601308.34
Net Profit
25961360.131%
Sharpe Ratio
5.239
Sortino Ratio
10.159
Probabilistic Sharpe Ratio
99.699%
Loss Rate
57%
Win Rate
43%
Profit-Loss Ratio
2.30
Alpha
6.246
Beta
-0.382
Annual Standard Deviation
1.186
Annual Variance
1.407
Information Ratio
5.074
Tracking Error
1.208
Treynor Ratio
-16.275
Total Fees
$148931329464.95
Estimated Strategy Capacity
$35000.00
Lowest Capacity Asset
LTCUSD 10B
Portfolio Turnover
256.12%
Drawdown Recovery
1511
#region imports
from AlgorithmImports import *
#endregion
#
# Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)
# https://creativecommons.org/licenses/by-nc-nd/4.0/
# CandleStick.py -- Pivot(s) calculator.
#
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.5.0.0.10862. Copyright 2014 QuantConnect Corporation.
#
########################################################
# Developed by Anastasios N. Bikos. ©DeepConscius All Rights Reserved.
#   # mpikos@live.com
#   # Copyright ~ ~ ~ 16/3/2023
#   # Version ~ ~ ~ a26.5
#   # ~ ~ ~
########################################################
import numpy as np

BULLISH = 1
BEARISH = 0

class CandleStick:
  def __init__(self, o, c, h, l, time):
    self.o = o
    self.c = c
    self.h = h
    self.l = l
    self.body = c - o
    self.range = h - l
    if self.body < 0:
      self.direction = BEARISH
      self.us = h - o
      self.ls = c - l
    elif self.body == 0:
      self.body = np.mean([o, c])
      self.direction = BULLISH
      self.us = h - c
      self.ls = o - l
    else:
      self.direction = BULLISH
      self.us = h - c
      self.ls = o - l
    if self.range == 0:
      self.range = np.mean([l, h])
    self.time = time
#region imports
from AlgorithmImports import *
#endregion
#
# Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)
# https://creativecommons.org/licenses/by-nc-nd/4.0/
# ChartAnalysis.py -- Utility function(s) to estimate volume swings patterns and volatility trends.
#
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.5.0.0.10862. Copyright 2014 QuantConnect Corporation.
#
########################################################
# Developed by Anastasios N. Bikos. ©DeepConscius All Rights Reserved.
#   # mpikos@live.com
#   # Copyright ~ ~ ~ 16/3/2023
#   # Version ~ ~ ~ a26.5
#   # ~ ~ ~
########################################################
BULLISH = 1
BEARISH = 0

def hammer(cs0, cs1):
    if cs0.direction == BEARISH:
        return False, 0x00
    elif cs0.us/abs(cs0.body) > .4:
        return False, 0x00
    elif abs(cs0.body)/cs0.range > .2:
        return False, 0x00
    # elif cs0.l > cs1.l:
    #     return False, 0
    return True, 0x01

def star(cs0, cs1):
    if cs0.direction == BULLISH:
        return False, 0x00
    elif cs0.ls/abs(cs0.body) > .2:
        return False, 0x00
    elif abs(cs0.body)/cs0.range > .3:
        return False, 0x00
    # elif cs0.h < cs1.h:
    #     return False, 0
    return True, 0x02

def bearish_engulfing(cs0, cs1):
    if cs0.direction == BULLISH:
        return False, 0
    elif cs1.direction == BEARISH:
        return False, 0
    elif cs1.c > cs0.o:
        return False, 0
    elif cs1.o < cs0.c:
        return False, 0
    elif cs1.h > cs0.h:
        return False, 0
    elif cs1.l < cs0.l:
        return False, 0
    return True, 0x20

def bullish_engulfing(cs0, cs1):
    if cs0.direction == BEARISH:
        return False, 0
    elif cs1.direction == BULLISH:
        return False, 0
    elif cs1.o > cs0.c:
        return False, 0
    elif cs1.c < cs0.o:
        return False, 0
    elif cs1.h > cs0.h:
        return False, 0
    elif cs1.l < cs0.l:
        return False, 0
    return True, 0x040

def piercing_line(cs0, cs1):
    if cs0.direction == BEARISH:
        return False, 0
    elif cs1.direction == BULLISH:
        return False, 0
    elif cs1.o < cs0.o:
        return False, 0
    elif cs1.c < cs0.c:
        return False, 0
    elif cs1.h < cs0.h:
        return False, 0
    elif cs1.l < cs0.l:
        return False, 0
    elif cs0.c < (cs1.range/2 + cs1.c):
        return False, 0
    return True, 0x80

def threeBears(bar1, bar2, bar3):
    if bar1.o > bar2.open:
        return False, 0
    elif bar2.high > bar3.high:
        return False, 0
    return True

def get_avg_range(data):
    sum = 0
    count = 0
    length = 0
    for cs in data:
        if count > 2:
            sum = sum + (float(cs[1]) - float(cs[2]))
            length += 1
        count += 1
    return sum/length

def major_move(cs, atr):
    if abs(cs.body) < atr:
        return False, 0
    elif cs.us/abs(cs.body) > .15:
        return False, 0
    elif cs.ls/abs(cs.body) > .15:
        return False, 0
    return True, 0x004

def gap_up(cs0, cs1):
    if cs1.h < cs0.l:
        return True, 0x008
    else:
        return False, 0

def gap_down(cs0, cs1):
    if cs1.l > cs0.h:
        return True, 0x010
    else:
        return False, 0

def black_marubozu(cs, atr):
    if cs.h != cs.o:
        return False, 0
    elif cs.l != cs.c:
        return False, 0
    elif cs.range < atr:
        return False, 0
    return True, 0x100

def white_marubozu(cs, atr):
    if cs.h != cs.c:
        return False, 0
    elif cs.l != cs.o:
        return False, 0
    elif cs.range < atr:
        return False, 0
    return True, 0x200

def bearish_doji(cs0, cs1):
    if abs(cs0.o-cs0.c)/cs0.range > .05:
        return False, 0
    elif abs(cs0.h - cs0.c)/cs0.range < .7:
        return False, 0
    elif abs(cs0.c - cs0.l)/cs0.range > .3:
        return False, 0
    elif cs0.h < cs1.h:
        return False, 0
    return True, 0x400

def bullish_doji(cs0, cs1):
    if abs(cs0.o-cs0.c)/cs0.range > .05:
        return False, 0
    elif abs(cs0.h - cs0.c)/cs0.range > .3:
        return False, 0
    elif abs(cs0.c - cs0.l)/cs0.range < .7:
        return False, 0
    elif cs0.l > cs1.l:
        return False, 0
    return True,0x800
#region imports
from AlgorithmImports import *
#endregion
#
# Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)
# https://creativecommons.org/licenses/by-nc-nd/4.0/
# RecvQuotes.py -- Main (volume) swing decision calculator.
#
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.5.0.0.10862. Copyright 2014 QuantConnect Corporation.
#
########################################################
# Developed by Anastasios N. Bikos. ©DeepConscius All Rights Reserved.
#   # mpikos@live.com
#   # Copyright ~ ~ ~ 16/3/2023
#   # Version ~ ~ ~ a26.5
#   # ~ ~ ~
########################################################
import pandas as pd
import datetime as datetime
import CandleStick as cs
import ChartAnalysis as analyze
import csv

def make_decision(value, time):
    if value:
        print ("OPEN TRADE")
        verbage = ''
        if value & 0x1:
            print("HAMMER")
            verbage += "HAMMER "
        if value & 0x2:
            print("STAR")
            verbage += "STAR "
        if value & 0x4:
            print("MAJOR MOVE")
            verbage += "MAJOR MOVE "
        if value & 0x8:
            print("GAP UP")
            verbage += "GAP UP "
        if value & 0x10:
            print("GAP DOWN")
            verbage += "GAP DOWN "
        if value & 0x20:
            print("BEARISH ENGULFING")
            verbage += "BEARISH ENGULFING "
        if value & 0x40:
            print("BULLISH ENGULFING")
            verbage += "BULLISH ENGULFING "
        if value & 0x80:
            print("PIERCING LINE")
            verbage += "PIERCING LINE "
        if value & 0x100:
            print("BLACK MARUBOZU")
            verbage += "BLACK MARUBOZU "
        if value & 0x200:
            print("WHITE MARUBOZU")
            verbage += "WHITE MARUBOZU "
        if value & 0x400:
            print("BEARISH DOJI")
            verbage += "BEARISH DOJI "
        if value & 0x800:
            print("BULLISH DOJI")
            verbage += "BULLISH DOJI "
            
        return verbage

def analyze_data(cs_0, cs_1, cs_2, atr):
    a, av = analyze.hammer(cs_0, cs_1)
    b, bv = analyze.star(cs_0, cs_1)
    c, cv = analyze.major_move(cs_0, atr)
    d, dv = analyze.gap_up(cs_0, cs_1)
    e, ev = analyze.gap_down(cs_0, cs_1)
    f, fv = analyze.bearish_engulfing(cs_0, cs_1)
    g, gv = analyze.bullish_engulfing(cs_0, cs_1)
    h, hv = analyze.piercing_line(cs_0, cs_1)
    i, iv = analyze.black_marubozu(cs_0, atr)
    j, jv = analyze.white_marubozu(cs_0, atr)
    k, kv = analyze.bearish_doji(cs_0, cs_1)
    l, lv = analyze.bullish_doji(cs_0, cs_1)
    # print(cs_0.time, "\t", a, "\t", b, "\t", c, "\t", d, "\t", e, "\t", f, "\t", g, "\t", h, "\t", i, "\t", j, "\t", k, "\t", l)
    value = av | bv | cv | dv | ev | fv | gv | hv | iv | jv | kv | lv
    verbage = make_decision(value, cs_0.time)
    
    return verbage

def get_last_three(fn):
    #allData = csv.reader(fn)
    atr = analyze.get_avg_range(fn)

    lines = fn
    row0 = lines[-1]
    row1 = lines[-2]
    row2 = lines[-3]

    return atr, row0, row1, row2

def get_daily(fn):
    atr, row0, row1, row2 = get_last_three(fn)

    line = row0
    a = float(line[3])
    b = float(line[4])
    c = float(line[1])
    d = float(line[2])
    e = line[0]
    cs_0 = cs.CandleStick(a,b,c,d,e)

    line = row1
    a = float(line[3])
    b = float(line[4])
    c = float(line[1])
    d = float(line[2])
    e = line[0]
    cs_1 = cs.CandleStick(a,b,c,d,e)

    line = row2
    a = float(line[3])
    b = float(line[4])
    c = float(line[1])
    d = float(line[2])
    e = line[0]
    cs_2 = cs.CandleStick(a,b,c,d,e)

    verbage = analyze_data(cs_0, cs_1, cs_2, atr)
    
    return verbage
#
# Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)
# https://creativecommons.org/licenses/by-nc-nd/4.0/
# System.py -- Main API core.
#
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.5.0.0.10862. Copyright 2014 QuantConnect Corporation.
#
########################################################
# Developed by Anastasios N. Bikos. ©DeepConscius All Rights Reserved.
#   # mpikos@live.com
#   # Copyright ~ ~ ~ 15/10/2023
#   # Version ~ ~ ~ a33.0
#   # ~ ~ ~
########################################################
from System import *
from QuantConnect.Data import *
from QuantConnect.Algorithm import *
from QuantConnect.Indicators import *
from QuantConnect.Securities import *
from QuantConnect.Data.Consolidators import *
from QuantConnect.Orders import OrderStatus
from QuantConnect import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Alphas import *
from QuantConnect.Data.Market import TradeBar
from AlgorithmImports import *

from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

import math
from math import floor
import random
import pandas as pd
import numpy as np
from datetime import timedelta, datetime
from datetime import timedelta
from collections import deque
from sklearn.preprocessing import MinMaxScaler
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import talib as ta
from statistics import mode

# Binary Classification with Sonar Dataset: Baseline
import xgboost as xgb
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import LSTM
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC, LinearSVC, NuSVC, SVR, NuSVR, OneClassSVM
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn import preprocessing
from collections import Counter

import RecvQuotes as RQ

class MarketDynamics(QCAlgorithm):
    global X
    X = 60
    global xn
    xn = int(float(60)/float(X))
    global daily_trades_allowance_quant
    daily_trades_allowance_quant = 0
    global minute_trades_allowance_quant_thresh
    minute_trades_allowance_quant_thresh = 1
    global daily_trades_allowance_quant_thresh
    daily_trades_allowance_quant_thresh = minute_trades_allowance_quant_thresh *24 *xn
    global minute_trades_allowance_quant
    minute_trades_allowance_quant = 0
    global daily_trade_flag_en
    daily_trade_flag_en = False
    global hourly_trade_flag_en
    hourly_trade_flag_en = False
    global bet_arr
    bet_arr = [0, 0]
    global hist_arr
    hist_arr = [0, 0]
    global trading_quantum
    trading_quantum = 1.0
    global start_equity_amount
    start_equity_amount = 50000
    global total_equity
    total_equity = [(0.01 *start_equity_amount)]
    global min_border
    min_border = -1
    global max_border
    max_border = +1
    global margins_border
    margins_border = [[-0, -1], [+0, +1]]
    global scaler
    global arr1
    arr1 = [-1,-1]
    global arr2
    arr2 = [-1,-1]
    global dataset
    dataset = [-1]
    global stopPriceBuy
    stopPriceBuy = -1
    global profit_factor
    profit_factor = 0.1
    global closeness_factor
    closeness_factor = 0.05
    global normalized
    normalized = []
    global comp_price
    comp_price = []
    global projected_price
    projected_price = []
    global __quantity
    __quantity = 0
    global day_close_price_arr
    day_close_price_arr = [-1, -1]
    global high_price_arr
    high_price_arr = [-1, -1]
    global low_price_arr
    low_price_arr = [-1, -1]
    global volume_arr
    volume_arr = [-1, -1]
    global open_price_arr
    open_price_arr = [-1, -1]
    global close_price_arr
    close_price_arr = [-1, -1]
    global datetime_arr
    datetime_arr = []
    global loss_factor
    loss_factor = 0.0125
    global rsi_interval
    rsi_interval = 14
    global U
    U = 12
    global Z
    Z = 1
    global scheduled_event_1
    scheduled_event_1 = None
    global symbol_minimum_trade_order_size
    symbol_minimum_trade_order_size = 0.5
    global verbage
    verbage = "None"
    global t_indicator_arr
    t_indicator_arr = []
    global delta_prediction_arr
    delta_prediction_arr = []
    global real
    global last_trade_order
    last_trade_order = "Null"
    global a0_arr
    a0_arr = []
    global offset
    offset = 1000
    global sign
    sign = +1
    global sign_
    sign_ = +1
    global _sign
    _sign = +1
    global weekly_stockprices_arr
    weekly_stockprices_arr = [[], [], [], []]
    global weekly_stockprices_arr1
    weekly_stockprices_arr1 = []
    global weekly_stockprices_arr2
    weekly_stockprices_arr2 = []
    global weekly_stockprices_arr3
    weekly_stockprices_arr3 = []
    global weekly_stockprices_arr4
    weekly_stockprices_arr4 = []
    global high_price_arr1
    high_price_arr1 = []
    global high_price_arr2
    high_price_arr2 = []
    global high_price_arr3
    high_price_arr3 = []
    global high_price_arr4
    high_price_arr4 = []
    global low_price_arr1
    low_price_arr1 = []
    global low_price_arr2
    low_price_arr2 = []
    global low_price_arr3
    low_price_arr3 = []
    global low_price_arr4
    low_price_arr4 = []
    global volume_arr1
    volume_arr1 = []
    global volume_arr2
    volume_arr2 = []
    global volume_arr3
    volume_arr3 = []
    global volume_arr4
    volume_arr4 = []
    global open_price_arr1
    open_price_arr1 = []
    global open_price_arr2
    open_price_arr2 = []
    global open_price_arr3
    open_price_arr3 = []
    global open_price_arr4
    open_price_arr4 = []
    global close_price_arr1
    close_price_arr1 = []
    global close_price_arr2
    close_price_arr2 = []
    global close_price_arr3
    close_price_arr3 = []
    global close_price_arr4
    close_price_arr4 = []
    global day_close_price_arr1
    day_close_price_arr1 = []
    global day_close_price_arr2
    day_close_price_arr2 = []
    global day_close_price_arr3
    day_close_price_arr3 = []
    global day_close_price_arr4
    day_close_price_arr4 = []
    global btcusd_a0
    btcusd_a0 = 0
    global ethusd_a0
    ethusd_a0 = 0
    global dotusd_a0
    dotusd_a0 = 0
    global ltcusd_a0
    ltcusd_a0 = 0
    global DD_arr
    DD_arr = []
    global total_equity_
    total_equity_ = [(0.01 *start_equity_amount)]
    global out_DD
    out_DD = [-1, -1]
    global sign_inp_arr
    sign_inp_arr = []
    global rsi_intra_daily
    rsi_intra_daily = 50
    global exp_factor
    exp_factor = 1.0
    global no_ctr
    no_ctr = [6, 6, 6, 6]
    global enable_live_mode
    enable_live_mode = True
    global take_profit_factor
    take_profit_factor = 0.30
    global mom_array
    mom_array = [[], [], [], []]
    global rsi_intra_daily_array
    rsi_intra_daily_array = [[], [], [], []]
    global exposure_risk_factor
    exposure_risk_factor = 0.1
    global dayscounter
    dayscounter = 0

    global episode_list
    episode_list = []
    global sign_arr
    sign_arr = []

    FastEmaPeriod = 12
    SlowEmaPeriod = 26

    def TakeProfit(self):
        global take_profit_factor

        if self.Portfolio.TotalUnrealizedProfit > 0 and self.Portfolio.TotalUnrealizedProfit >= (take_profit_factor *self.Portfolio.TotalPortfolioValue):
            for ticker in self.tickers:
                self.EmitInsights(
                    # Creates an insight for our symbol, predicting that it will move down within the fast ema period number of days
                    Insight.Price(ticker, timedelta(self.FastEmaPeriod), InsightDirection.Down)
                )
                
                self.Liquidate(ticker)
            
                self.SetHoldings(ticker, 0)
            
            self.Debug("Take Profit!")

    def ControlExposureLevel(self):
        global total_equity_
        global exp_factor
        global _sign
        global no_ctr

        delta_total_equity = (total_equity_[-1] - total_equity_[-2]) / total_equity_[-2]

        if delta_total_equity < 0 and np.abs(delta_total_equity) > 0.0125:
            _sign = 0

            no_ctr = [6, 6, 6, 6]
        else:
            _sign = +1

            no_ctr = [0, 0, 0, 0]

        for ticker in self.tickers:
            if self.Portfolio[ticker].UnrealizedProfit < 0 and np.abs(self.Portfolio[ticker].UnrealizedProfit) >= (loss_factor *self.Portfolio.TotalPortfolioValue):
                if ticker == self.targets1:
                    no_ctr[0] = 6
                elif ticker == self.targets2:
                    no_ctr[1] = 6
                elif ticker == self.targets3:
                    no_ctr[2] = 6
                elif ticker == self.targets4:
                    no_ctr[3] = 6
            else:
                if ticker == self.targets1:
                    no_ctr[0] = 0
                elif ticker == self.targets2:
                    no_ctr[1] = 0
                elif ticker == self.targets3:
                    no_ctr[2] = 0
                elif ticker == self.targets4:
                    no_ctr[3] = 0

    def ControlDrawdownLevel(self):
        global total_equity_
        global DD_arr
        
        self.account_leverage = self.Portfolio.TotalHoldingsValue / self.Portfolio.TotalPortfolioValue
        
        total_equity_ = np.append(total_equity_, self.Portfolio.TotalPortfolioValue)
        
        if total_equity_[-1] != 0 and self.account_leverage != 0:
            diff = float(np.abs(total_equity_[-1] - total_equity_[-2])) / float(total_equity_[-1])
            
            drawdown = float(diff) / float(self.account_leverage)
            
            DD_arr = np.append(DD_arr, self.truncate(drawdown, 2))
            
            if drawdown >= 0.10:
                self.Debug("Leverage control ahead!")
                
                for ticker in self.tickers:
                    self.EmitInsights(
                        # Creates an insight for our symbol, predicting that it will move down within the fast ema period number of days
                        Insight.Price(ticker, timedelta(self.FastEmaPeriod), InsightDirection.Down)
                    )
                    
                    self.Liquidate(ticker)
                
                    self.SetHoldings(ticker, 0)
    
    def truncate(self, number, decimals=0):
        """
        Returns a value truncated to a specific number of decimal places.
        """
        if not isinstance(decimals, int):
            raise TypeError("decimal places must be an integer.")
        elif decimals < 0:
            raise ValueError("decimal places has to be 0 or more.")
        elif decimals == 0:
            return math.trunc(number)
    
        factor = 10.0 ** decimals
        return math.trunc(number * factor) / factor
    
    def create_dataset(self, dataset, look_back=1):
        dataX, dataY = [], []
        for i in range(len(dataset)-look_back-1):
            a = dataset[i:(i+look_back), 0]
            dataX.append(a)
            dataY.append(dataset[i + look_back, 0])
        
        return np.array(dataX), np.array(dataY)
    
    def scale(self, X, x_min, x_max):
        nom = (X-X.min(axis=0))*(x_max-x_min)
        denom = X.max(axis=0) - X.min(axis=0)
        denom[denom==0] = 1
        return x_min + nom/denom
        
    def LSTM(self, dataset, scaler_factor):
        dataset = dataset.reshape(-1, 1)
        
        # split into train and test sets
        train_size = int(len(dataset) * 0.67)
        test_size = len(dataset) - train_size
        train, test = dataset[0:train_size,:], dataset[train_size:len(dataset),:]
        
        # reshape into X=t and Y=t+1
        look_back = 10
        trainX, trainY = self.create_dataset(train, look_back)
        testX, testY = self.create_dataset(test, look_back)
        
        # reshape input to be [samples, time steps, features]
        trainX = np.reshape(trainX, (trainX.shape[0], 1, trainX.shape[1]))
        testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1]))
        
        # create and fit the LSTM network
        model = Sequential()
        model.add(LSTM(36, input_shape=(1, look_back)))
        model.add(Dense(1))
        model.compile(loss='binary_crossentropy', optimizer='adam')
        model.fit(trainX, trainY, epochs=10, batch_size=1000, verbose=0)
        
        # make predictions
        trainPredict = model.predict(trainX)
        testPredict = model.predict(testX)
        
        # invert predictions
        trainPredict = scaler_factor.inverse_transform(trainPredict)
        trainY = scaler_factor.inverse_transform([trainY])
        testPredict = scaler_factor.inverse_transform(testPredict)
        testY = scaler_factor.inverse_transform([testY])
        
        # calculate root mean squared error
        trainScore = math.sqrt(mean_squared_error(trainY[0], trainPredict[:,0]))
        print('Train Score: %.2f RMSE' % (trainScore))
        testScore = math.sqrt(mean_squared_error(testY[0], testPredict[:,0]))
        print('Test Score: %.2f RMSE' % (testScore))
        
        return [np.mean(testPredict[:, 0])]
            
    def ML_engine(self, history):
        import xgboost as xgb
        from sklearn.model_selection import train_test_split
        from sklearn.model_selection import KFold
        from sklearn.model_selection import cross_val_score
        
        # load pima indians dataset
        #print(history)
        
        dataset = history
      
        # create {Classifier} model
        model = xgb.XGBClassifier(learning_rate=0.1, n_estimators=100, max_depth=4,
        min_child_weight=6, gamma=0, subsample=0.8, colsample_bytree=0.8, reg_alpha=0.005,
        objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27)
        
        X = np.array(dataset[0:(len(dataset) - 1):2]).reshape(-1, 1).tolist()
        Y = np.array(dataset[1:(len(dataset) - 0):2]).reshape(-1, 1).tolist()
            
        X = pd.DataFrame(X)
        y = pd.DataFrame(Y)
            
        data_dmatrix = xgb.DMatrix(data=X, label=y)
    
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=None)

        from sklearn.preprocessing import LabelEncoder
        le = LabelEncoder()
        y_train = le.fit_transform(y_train)
    
        model.fit(X_train, y_train)
        
        kfold = KFold(n_splits=2, random_state=None)
        results = cross_val_score(model, X_train, y_train, cv=kfold)
        
        #self.calc_net_perf(model, X_train, X_test, y_train, y_test, prediction)

        if np.isnan(np.mean(results)):
            # calculate predictions
            prediction = model.predict(pd.DataFrame(np.array(X_test).reshape(-1, 1).tolist()))
            print(prediction)
        else:
            prediction = results

        prediction = int(np.round(np.mean(prediction)))
    
        return prediction
        
    def ML_engine1(self, history):
        import xgboost as xgb
        from sklearn.model_selection import train_test_split
        from sklearn.model_selection import KFold
        from sklearn.model_selection import cross_val_score
        
        # load pima indians dataset
        #print(history)
        
        dataset = history
      
        # create {Classifier} model
        model = xgb.XGBRegressor(base_score=0.5, booster='gblinear', colsample_bylevel=None,
             colsample_bynode=None, colsample_bytree=None, gamma=None,
             gpu_id=-1, importance_type='gain', interaction_constraints=None,
             learning_rate=0.15, max_delta_step=None, max_depth=15,
             min_child_weight=3, monotone_constraints=None,
             n_estimators=100, n_jobs=16, num_parallel_tree=None,
             random_state=0, reg_alpha=0, reg_lambda=0, scale_pos_weight=1,
             subsample=None, tree_method=None, validate_parameters=1,
             verbosity=None)
        
        X = np.array(dataset[0:(len(dataset) - 1):2]).reshape(-1, 1).tolist()
        Y = np.array(dataset[1:(len(dataset) - 0):2]).reshape(-1, 1).tolist()
            
        X = pd.DataFrame(X)
        y = pd.DataFrame(Y)
            
        data_dmatrix = xgb.DMatrix(data=X, label=y)
    
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=None)
    
        model.fit(X_train, y_train)

        kfold = KFold(n_splits=10, random_state=None)
        results = cross_val_score(model, X_train, y_train, cv=kfold)
        
        # calculate predictions
        prediction = np.mean(results)
        
        #self.calc_net_perf(model, X_train, X_test, y_train, y_test, prediction)
    
        return prediction
        
    def LinearRegr(self, history):
        # Fitting Linear Regression to the dataset
        from sklearn.linear_model import LinearRegression
        
        # load pima indians dataset
        dataset = history
       
        #minimum = np.min(dataset)
        #maximum = np.max(dataset)
    
        X = np.array(dataset[0:(len(dataset) - 1):2]).reshape(-1, 1).tolist()
        y = np.array(dataset[1:(len(dataset) - 0):2]).reshape(-1, 1).tolist()
                
        lin_reg = LinearRegression()
    
        lin_reg.fit(X, y)
        
        # Predicting a new result with Linear Regression
        out = lin_reg.predict([[dataset[-1]]])
        
        return out

    def GetCloseProfit(self):
        global profit_factor

        for ticker in self.tickers:
            if self.Portfolio[ticker].UnrealizedProfit > 0 and self.Portfolio[ticker].UnrealizedProfit >= (profit_factor *self.Portfolio.TotalPortfolioValue):
                self.Log("{Manually} closing open order(s)..")
                
                self.Liquidate(ticker)
                    
                self.SetHoldings(ticker, 0)

    def GetCloseLoss(self):
        global loss_factor

        for ticker in self.tickers:
            if self.Portfolio[ticker].UnrealizedProfit < 0 and np.abs(self.Portfolio[ticker].UnrealizedProfit) >= (loss_factor *self.Portfolio.TotalPortfolioValue):
                self.Log("{Manually} closing open order(s)..")
                
                self.Liquidate(ticker)
                    
                self.SetHoldings(ticker, 0)
            
    def GetClose(self):
        for ticker in self.tickers:
            self.Liquidate(ticker)
            
            self.SetHoldings(ticker, 0)
            
            self.Log("Liquidating..")
           
    def AdaptEquityInvestement(self):
        global trading_quantum
        
        trading_quantum += 1.0
        
        self.Log("Month change!")
        self.Log("Portfolio invested cash (current):: " + str(self.Portfolio.TotalMarginUsed))

    def GetWeekData(self):
        global weekly_stockprices_arr
        global weekly_stockprices_arr1
        global weekly_stockprices_arr2
        global weekly_stockprices_arr3
        global weekly_stockprices_arr4
        global btcusd_a0
        global ethusd_a0
        global dotusd_a0
        global ltcusd_a0

        weekly_stockprices_arr1 = np.append(weekly_stockprices_arr1, btcusd_a0)
        weekly_stockprices_arr2 = np.append(weekly_stockprices_arr2, ethusd_a0)
        weekly_stockprices_arr3 = np.append(weekly_stockprices_arr3, dotusd_a0)
        weekly_stockprices_arr4 = np.append(weekly_stockprices_arr4, ltcusd_a0)

        weekly_stockprices_arr = [weekly_stockprices_arr1, weekly_stockprices_arr2, weekly_stockprices_arr3, weekly_stockprices_arr4]

    def Initialize(self):
        global X
        global U
        global Z
        global scheduled_event_1
        
        #Brokerage model and account type:
        self.SetBrokerageModel(BrokerageName.ALPHA_STREAMS, AccountType.Margin)
        
        self.SetStartDate(2020, 1, 1)  # Set Start Date
        self.SetCash(1000000)
        #self.SetCash("BTC", start_equity_amount)  # Set Strategy Cash
        # Select asset data
        self.tickers = ["BTCUSD", "ETHUSD", "BTCEUR", "LTCUSD"]

        self.leverage_targets1 = 10.0
        self.leverage_targets2 = 5.0
        self.leverage_targets3 = 3.3
        self.leverage_targets4 = 5.0
        self.leverage_targets_default = 1.0

        self.btcusd = self.AddCrypto(self.tickers[0], Resolution.HOUR, Market.KRAKEN, leverage=self.leverage_targets1).Symbol
        self.targets1 = "BTCUSD"
        self.ethusd = self.AddCrypto(self.tickers[1], Resolution.HOUR, Market.KRAKEN, leverage=self.leverage_targets2).Symbol
        self.targets2 = "ETHUSD"
        self.dotusd = self.AddCrypto(self.tickers[2], Resolution.HOUR, Market.KRAKEN, leverage=self.leverage_targets3).Symbol
        self.targets3 = "BTCEUR"
        self.ltcusd = self.AddCrypto(self.tickers[3], Resolution.HOUR, Market.KRAKEN, leverage=self.leverage_targets4).Symbol
        self.targets4 = "LTCUSD"

        self.max_portfolio_leverage = 1.5 # for crypto margin accounts; set 1.0 for cash-like behavior
        self.min_free_margin_ratio = 0.10 # stop opening new risk if remaining margin < 10% of total
        self.last_reject_time = {} # Symbol -> datetime, for cooldown
        self.reject_cooldown_minutes = 60

        # Create a Rolling Window to keep the 1440 decimal
        self.closeWindow1 = RollingWindow[float](1440)
        self.closeWindow2 = RollingWindow[float](1440)
        self.closeWindow3 = RollingWindow[float](1440)
        self.closeWindow4 = RollingWindow[float](1440)
        
        # the scheduling methods return the ScheduledEvent object which can be used 
        # for other things here I set the event up to check the portfolio value every
        # X minutes, and liquidate if we have too many losses
        scheduled_event_1 = self.Schedule.On(self.DateRules.EveryDay(),  \
            self.TimeRules.Every(timedelta(minutes=U *X)), \
            self.ChangeHourFlag)

        self.Schedule.On(self.DateRules.WeekStart("BTCUSD"), \
            self.TimeRules.At(0, 0, 0), \
            self.GetWeekData)

        self.Schedule.On(self.DateRules.WeekStart("ETHUSD"), \
            self.TimeRules.At(0, 0, 0), \
            self.GetWeekData)

        self.Schedule.On(self.DateRules.WeekStart("BTCEUR"), \
            self.TimeRules.At(0, 0, 0), \
            self.GetWeekData)

        self.Schedule.On(self.DateRules.WeekStart("LTCUSD"), \
            self.TimeRules.At(0, 0, 0), \
            self.GetWeekData)        
        
        self.Schedule.On(self.DateRules.MonthStart("BTCUSD"), \
            self.TimeRules.At(0, 0, 0), \
            self.AdaptEquityInvestement)

        self.Schedule.On(self.DateRules.MonthStart("ETHUSD"), \
            self.TimeRules.At(0, 0, 0), \
            self.AdaptEquityInvestement)

        self.Schedule.On(self.DateRules.MonthStart("BTCEUR"), \
            self.TimeRules.At(0, 0, 0), \
            self.AdaptEquityInvestement)

        self.Schedule.On(self.DateRules.MonthStart("LTCUSD"), \
            self.TimeRules.At(0, 0, 0), \
            self.AdaptEquityInvestement)

        self.Schedule.On(self.DateRules.EveryDay(),  \
            self.TimeRules.Every(timedelta(minutes=(U *X))), \
            self.ControlDrawdownLevel)

        self.Schedule.On(self.DateRules.EveryDay(),  \
            self.TimeRules.Every(timedelta(minutes=(U *X))), \
            self.ControlExposureLevel)

        '''
        self.Schedule.On(self.DateRules.EveryDay(),  \
            self.TimeRules.Every(timedelta(minutes=(Z *X))), \
            self.GetCloseLoss)
        '''

        self.Schedule.On(self.DateRules.EveryDay(),  \
            self.TimeRules.Every(timedelta(minutes=(U *X))), \
            self.TakeProfit)

        self.Schedule.On(self.DateRules.EveryDay(),  
            self.TimeRules.At(9, 31),  
            Action(self.One))
        
        # Feed in 1440 bars before start date:
        self.SetWarmup(1440)

        self.warmup_period = 1440
        
        consolidator1 = TradeBarConsolidator(timedelta(1))
        consolidator1.DataConsolidated += self.OnDailyData
        self.SubscriptionManager.AddConsolidator("BTCUSD", consolidator1)

        consolidator2 = TradeBarConsolidator(timedelta(1))
        consolidator2.DataConsolidated += self.OnDailyData
        self.SubscriptionManager.AddConsolidator("ETHUSD", consolidator2)

        consolidator3 = TradeBarConsolidator(timedelta(1))
        consolidator3.DataConsolidated += self.OnDailyData
        self.SubscriptionManager.AddConsolidator("BTCEUR", consolidator3)

        consolidator4 = TradeBarConsolidator(timedelta(1))
        consolidator4.DataConsolidated += self.OnDailyData
        self.SubscriptionManager.AddConsolidator("LTCUSD", consolidator4)
        
        consolidatorm1 = TradeBarConsolidator(60)
        consolidatorm1.DataConsolidated += self.OnMinuteData
        self.SubscriptionManager.AddConsolidator("BTCUSD", consolidatorm1)

        consolidatorm2 = TradeBarConsolidator(60)
        consolidatorm2.DataConsolidated += self.OnMinuteData
        self.SubscriptionManager.AddConsolidator("ETHUSD", consolidatorm2)

        consolidatorm3 = TradeBarConsolidator(60)
        consolidatorm3.DataConsolidated += self.OnMinuteData
        self.SubscriptionManager.AddConsolidator("BTCEUR", consolidatorm3)

        consolidatorm4 = TradeBarConsolidator(60)
        consolidatorm4.DataConsolidated += self.OnMinuteData
        self.SubscriptionManager.AddConsolidator("LTCUSD", consolidatorm4)

        self.daily1 = RollingWindow[TradeBar](2)
        self.minute1 = RollingWindow[TradeBar](2)
        self.window1 = RollingWindow[TradeBar](2)

        self.daily2 = RollingWindow[TradeBar](2)
        self.minute2 = RollingWindow[TradeBar](2)
        self.window2 = RollingWindow[TradeBar](2)

        self.daily3 = RollingWindow[TradeBar](2)
        self.minute3 = RollingWindow[TradeBar](2)
        self.window3 = RollingWindow[TradeBar](2)

        self.daily4 = RollingWindow[TradeBar](2)
        self.minute4 = RollingWindow[TradeBar](2)
        self.window4 = RollingWindow[TradeBar](2)
    
        self._newHour = False
        self._newDay = False
        
        global daily_trade_flag_en
        daily_trade_flag_en = False
        global hourly_trade_flag_en
        hourly_trade_flag_en = False

        self.dayswarmup = 14
        
        self.conf_swing_level = 0.0

        self.dataframe = [[], [], [], []]
        self.trainsignaldatabase = [[], [], [], []]
        self.deltapricesdatabase = [[], [], [], []]

        self.feature_window = (((2 *U) - 1) *60)

        self.mom_arr = []
        
    def One(self):
        if not (self.window1.IsReady and self.daily1.IsReady and self.minute1.IsReady): return
        if not (self.window2.IsReady and self.daily2.IsReady and self.minute2.IsReady): return
        if not (self.window3.IsReady and self.daily3.IsReady and self.minute3.IsReady): return
        if not (self.window4.IsReady and self.daily4.IsReady and self.minute4.IsReady): return
        currBar1 = self.window1[0].Close
        yesterdayc1 = self.daily1[1].Close
        minuteBarC1 = self.minute1[1].Close
        minuteBar01 = self.minute1[1].Open

        currBar2 = self.window2[0].Close
        yesterdayc2 = self.daily2[1].Close
        minuteBarC2 = self.minute2[1].Close
        minuteBar02 = self.minute2[1].Open

        currBar3 = self.window3[0].Close
        yesterdayc3 = self.daily3[1].Close
        minuteBarC3 = self.minute3[1].Close
        minuteBar03 = self.minute3[1].Open

        currBar4 = self.window4[0].Close
        yesterdayc4 = self.daily4[1].Close
        minuteBarC4 = self.minute4[1].Close
        minuteBar04 = self.minute4[1].Open
        
    # Add daily bar to daily rolling window
    def OnDailyData(self, sender, bar):
        self.daily1.Add(bar)
        self.daily2.Add(bar)
        self.daily3.Add(bar)
        self.daily4.Add(bar)
        
    def OnMinuteData(self, sender, bar):
        self.minute1.Add(bar)
        self.minute2.Add(bar)
        self.minute3.Add(bar)
        self.minute4.Add(bar)
    
    def ChangeHourFlag(self):
        self._newHour = True
        
    def OnEndOfDay(self):
        self._newDay = True

    def SafeMarketOrder(self, symbol, target_percent, tag="rebalance"):
        # 1) avoid stacking orders (keep your edited guard style)
        if self.Transactions.GetOpenOrders(symbol):
            return None

        sec = self.Securities[symbol]
        if not sec.HasData or sec.Price <= 0:
            return None

        # 2) (optional) don’t trade during warmup
        if self.IsWarmingUp:
            return None

        # 3) hard cap the target exposure (adjust to taste)
        # for cash-like crypto, keep <= 1.0; for margin, you can allow >1 but be careful
        max_abs_target = 1.0
        target_percent = max(-max_abs_target, min(max_abs_target, float(target_percent)))

        # 4) get the *order quantity* that matches the target % and respects buying power
        qty = self.CalculateOrderQuantity(symbol, target_percent)  # QC helper
        if qty is None or abs(qty) < 1e-8:
            return None

        # 5) place the order (delta quantity)
        return self.MarketOrder(symbol, qty, tag=tag)

    def OnOrderEvent(self, orderEvent: OrderEvent):
        if orderEvent.Status == OrderStatus.Invalid:
            self.last_reject_time[orderEvent.Symbol] = self.Time
        if orderEvent.Status == OrderStatus.Canceled:
            # sometimes buying power rejections show as canceled in certain models
            self.last_reject_time[orderEvent.Symbol] = self.Time

    def OnData(self, data):
        global daily_trades_allowance_quant
        global daily_trades_allowance_quant_thresh
        global minute_trades_allowance_quant
        global minute_trades_allowance_quant_thresh
        global daily_trade_flag_en
        global hourly_trade_flag_en
        global bet_arr
        global hist_arr
        global arr1
        global arr2
        global min_border
        global max_border
        global trading_quantum
        global X
        global scaler
        global margins_border
        global dataset
        global profit_factor
        global normalized
        global projected_price
        global rsi_interval
        global __quantity
        global total_equity
        global day_close_price_arr
        global high_price_arr1
        global high_price_arr2
        global high_price_arr3
        global high_price_arr4
        global low_price_arr1
        global low_price_arr2
        global low_price_arr3
        global low_price_arr4
        global volume_arr1
        global volume_arr2
        global volume_arr3
        global volume_arr4
        global datetime_arr
        global open_price_arr1
        global open_price_arr2
        global open_price_arr3
        global open_price_arr4
        global close_price_arr1
        global close_price_arr2
        global close_price_arr3
        global close_price_arr4
        global day_close_price_arr1
        global day_close_price_arr2
        global day_close_price_arr3
        global day_close_price_arr4
        global verbage
        global DD_arr
        global t_indicator_arr
        global delta_prediction_arr
        global real
        global last_trade_order
        global a0_arr
        global btcusd_a0
        global ethusd_a0
        global dotusd_a0
        global ltcusd_a0
        global offset
        global sign
        global sign_
        global weekly_stockprices_arr
        global out_DD
        global sign_inp_arr
        global rsi_intra_daily
        global exp_factor
        global no_ctr
        global episode_list
        global sign_arr
        global _sign
        global mom_array
        global rsi_intra_daily_array
        global exposure_risk_factor
        global dayscounter
        global enable_live_mode

        for ticker in self.tickers:
            if data.ContainsKey(ticker):
                # Add crypto bar close in the rolling window
                if ticker == "BTCUSD":
                    self.closeWindow1.Add(data["BTCUSD"].Close)
                elif ticker == "ETHUSD":
                    self.closeWindow2.Add(data["ETHUSD"].Close)
                elif ticker == "BTCEUR":
                    self.closeWindow3.Add(data["BTCEUR"].Close)
                elif ticker == "LTCUSD":
                    self.closeWindow4.Add(data["LTCUSD"].Close)
        
        for ticker in self.tickers:
            if data[ticker] is None : return
        
         # Wait for window(s) to be ready.
        if not self.closeWindow1.IsReady: return
        if not self.closeWindow2.IsReady: return
        if not self.closeWindow3.IsReady: return
        if not self.closeWindow4.IsReady: return
    
        for ticker in self.tickers:
            if data.Bars.ContainsKey(ticker):
                if ticker == "BTCUSD":
                    self.window1.Add(data.Bars["BTCUSD"])
                elif ticker == "ETHUSD":
                    self.window2.Add(data.Bars["ETHUSD"])
                elif ticker == "BTCEUR":
                    self.window3.Add(data.Bars["BTCEUR"])
                elif ticker == "LTCUSD":
                    self.window4.Add(data.Bars["LTCUSD"])
        
        if not (self.window1.IsReady and self.daily1.IsReady): return
        if not (self.window2.IsReady and self.daily2.IsReady): return
        if not (self.window3.IsReady and self.daily3.IsReady): return
        if not (self.window4.IsReady and self.daily4.IsReady): return
    
        # fix random seed for reproducibility
        np.random.seed(7)

        '''
        self.GetCloseLoss()
        self.GetCloseProfit()
        '''
        
        if self._newDay == True:
            daily_trades_allowance_quant = 0
            daily_trade_flag_en = True
            self._newDay = False

            dayscounter += 1

            if dayscounter >= self.dayswarmup:
                '''enable_live_mode = True'''
                exposure_risk_factor += 0.1

            if exposure_risk_factor > 4.0:
                exposure_risk_factor = 4.0
 
            self.Log("Day change!")
        
        if self._newHour == True:
            minute_trades_allowance_quant = 0
            hourly_trade_flag_en = True
            self._newHour = False
            
            open_1 = np.array(self.daily1[1].Open, float).ravel()
            open_price_arr1 = np.append(open_price_arr1, open_1)
            open_price_arr1 = open_price_arr1[-self.warmup_period:]

            open_2 = np.array(self.daily2[1].Open, float).ravel()
            open_price_arr2 = np.append(open_price_arr2, open_2)
            open_price_arr2 = open_price_arr2[-self.warmup_period:]

            open_3 = np.array(self.daily3[1].Open, float).ravel()
            open_price_arr3 = np.append(open_price_arr3, open_3)
            open_price_arr3 = open_price_arr3[-self.warmup_period:]

            open_4 = np.array(self.daily4[1].Open, float).ravel()
            open_price_arr4 = np.append(open_price_arr4, open_4)
            open_price_arr4 = open_price_arr4[-self.warmup_period:]
        
            close_1 = np.array(self.daily1[1].Close, float).ravel()
            close_price_arr1 = np.append(close_price_arr1, close_1)
            close_price_arr1 = close_price_arr1[-self.warmup_period:]

            close_2 = np.array(self.daily2[1].Close, float).ravel()
            close_price_arr2 = np.append(close_price_arr2, close_2)
            close_price_arr2 = close_price_arr2[-self.warmup_period:]

            close_3 = np.array(self.daily3[1].Close, float).ravel()
            close_price_arr3 = np.append(close_price_arr3, close_3)
            close_price_arr3 = close_price_arr3[-self.warmup_period:]

            close_4 = np.array(self.daily4[1].Close, float).ravel()
            close_price_arr4 = np.append(close_price_arr4, close_4)
            close_price_arr4 = close_price_arr4[-self.warmup_period:]
            
            high_1 = self.daily1[1].High
            high_price_arr1 = np.append(high_price_arr1, high_1)
            high_price_arr1 = high_price_arr1[-self.warmup_period:]

            high_2 = self.daily2[1].High
            high_price_arr2 = np.append(high_price_arr2, high_2)
            high_price_arr2 = high_price_arr2[-self.warmup_period:]

            high_3 = self.daily3[1].High
            high_price_arr3 = np.append(high_price_arr3, high_3)
            high_price_arr3 = high_price_arr3[-self.warmup_period:]

            high_4 = self.daily4[1].High
            high_price_arr4 = np.append(high_price_arr4, high_4)
            high_price_arr4 = high_price_arr4[-self.warmup_period:]
            
            low_1 = self.daily1[1].Low
            low_price_arr1 = np.append(low_price_arr1, low_1)
            low_price_arr1 = low_price_arr1[-self.warmup_period:]

            low_2 = self.daily2[1].Low
            low_price_arr2 = np.append(low_price_arr2, low_2)
            low_price_arr2 = low_price_arr2[-self.warmup_period:]

            low_3 = self.daily3[1].Low
            low_price_arr3 = np.append(low_price_arr3, low_3)
            low_price_arr3 = low_price_arr3[-self.warmup_period:]

            low_4 = self.daily4[1].Low
            low_price_arr4 = np.append(low_price_arr4, low_4)
            low_price_arr4 = low_price_arr4[-self.warmup_period:]
    
            yesterdayc1 = self.daily1[1].Close
            day_close_price_arr1 = np.append(day_close_price_arr1, yesterdayc1)
            day_close_price_arr1 = day_close_price_arr1[-self.warmup_period:]

            yesterdayc2 = self.daily2[1].Close
            day_close_price_arr2 = np.append(day_close_price_arr2, yesterdayc2)
            day_close_price_arr2 = day_close_price_arr2[-self.warmup_period:]

            yesterdayc3 = self.daily3[1].Close
            day_close_price_arr3 = np.append(day_close_price_arr3, yesterdayc3)
            day_close_price_arr3 = day_close_price_arr3[-self.warmup_period:]

            yesterdayc4 = self.daily4[1].Close
            day_close_price_arr4 = np.append(day_close_price_arr4, yesterdayc4)
            day_close_price_arr4 = day_close_price_arr4[-self.warmup_period:]
            
            volume1 = self.daily1[1].Volume
            volume_arr1 = np.append(volume_arr1, volume1)
            volume_arr1 = volume_arr1[-self.warmup_period:]

            volume2 = self.daily2[1].Volume
            volume_arr2 = np.append(volume_arr2, volume2)
            volume_arr2 = volume_arr2[-self.warmup_period:]

            volume3 = self.daily3[1].Volume
            volume_arr3 = np.append(volume_arr3, volume3)
            volume_arr3 = volume_arr3[-self.warmup_period:]

            volume4 = self.daily4[1].Volume
            volume_arr4 = np.append(volume_arr4, volume4)
            volume_arr4 = volume_arr4[-self.warmup_period:]
            
            self.Log("(Virtual) Hour change!")
        else:
            return

        day_close_price_arr = [day_close_price_arr1, day_close_price_arr2, day_close_price_arr3, day_close_price_arr4]
        open_price_arr = [open_price_arr1, open_price_arr2, open_price_arr3, open_price_arr4]
        high_price_arr = [high_price_arr1, high_price_arr2, high_price_arr3, high_price_arr4]
        low_price_arr = [low_price_arr1, low_price_arr2, low_price_arr3, low_price_arr4]
        close_price_arr = [close_price_arr1, close_price_arr2, close_price_arr3, close_price_arr4]
        volume_arr = [volume_arr1, volume_arr2, volume_arr3, volume_arr4]
                    
        self.Debug("Current trade date:" + "\t" + str(self.Time))
    
        self.Log(str(self.Portfolio.TotalPortfolioValue))

        self.closeWindow = [self.closeWindow1, self.closeWindow2, self.closeWindow3, self.closeWindow4]

        datetime_arr = np.append(datetime_arr, self.Time.strftime('%Y-%m-%d'))
        
        ticker_idx = 0
        for ticker in self.tickers:
            tmp_arr_values = []
            tmp_arr_values1 = []
            tmp_arr_values2 = []
            for index in range(1439, 0, -1):
                tmp_arr_values = np.append(tmp_arr_values, self.closeWindow[ticker_idx][index])
                
                delta = (self.closeWindow[ticker_idx][(index - 1)] - self.closeWindow[ticker_idx][index])

                tmp_arr_values1 = np.append(tmp_arr_values1, delta)

                if self.closeWindow[ticker_idx][index] <= self.closeWindow[ticker_idx][(index - 1)]:
                    signal = 1
                else:
                    signal = 0
                    
                tmp_arr_values1 = np.append(tmp_arr_values1, signal)
        
            self.dataframe[ticker_idx] = tmp_arr_values
            self.deltapricesdatabase[ticker_idx] = tmp_arr_values1
            self.trainsignaldatabase[ticker_idx] = tmp_arr_values2

            self.hist = self.dataframe[ticker_idx]
            
            historical_train_data = self.hist

            a0_arr = np.append(a0_arr, np.mean(historical_train_data))
            
            stockprices = historical_train_data
            
            upperband, middleband, lowerband = ta.BBANDS(np.array(stockprices).ravel()*100000, timeperiod=90, nbdevup=2, nbdevdn=2,matype=0)
            
            upVal = upperband[-1]/100000
            middleVal = middleband[-1]/100000
            lowVal =  lowerband[-1]/100000

            a = np.array([upVal, middleVal, lowVal])
            a0 = self.closeWindow[ticker_idx][0]
            projected_price = a.flat[np.abs(a - a0).argmin()]
            projected_price = projected_price[np.logical_not(np.isnan(projected_price))]
            
            if len(datetime_arr) >= 5:
                # Correct column extraction + 1D flatten
                hp = np.asarray(high_price_arr)[:, ticker_idx].ravel()
                lp = np.asarray(low_price_arr)[:, ticker_idx].ravel()
                op = np.asarray(open_price_arr)[:, ticker_idx].ravel()
                cp = np.asarray(close_price_arr)[:, ticker_idx].ravel()
                vol = np.asarray(volume_arr)[:, ticker_idx].ravel()
                dcp = np.asarray(day_close_price_arr)[:, ticker_idx].ravel()

                dt = np.asarray(datetime_arr).ravel()

                # Make all vectors same length (trim to shortest)
                n = min(len(dt), len(hp), len(lp), len(op), len(cp), len(vol), len(dcp))
                dt, hp, lp, op, cp, vol, dcp = dt[:n], hp[:n], lp[:n], op[:n], cp[:n], vol[:n], dcp[:n]

                attribute = np.column_stack((dt, hp, lp, op, cp, vol, dcp)).tolist()
                if np.asarray(attribute).ndim > 1:
                    verbage = RQ.get_daily(np.asarray(attribute))
            else:
                verbage = "NONE"

            self.Debug(str(verbage))
            
            if len(day_close_price_arr) >= 14:
                real1 = ta.AD(np.array(high_price_arr[ticker_idx][-14:], float).ravel(), np.array(low_price_arr[ticker_idx][-14:], float).ravel(), np.array(day_close_price_arr[ticker_idx][-14:], float).ravel(), np.array(volume_arr[ticker_idx][-14:], float).ravel())
                real1 = np.mean(real1[np.logical_not(np.isnan(real1))])
            else:
                real1 = -1.0

            if len(day_close_price_arr) >= 14:
                real2 = ta.MFI(high_price_arr[ticker_idx], low_price_arr[ticker_idx], close_price_arr[ticker_idx], volume_arr[ticker_idx], timeperiod=14)
                real2 = np.mean(real2[np.logical_not(np.isnan(real2))])
            else:
                real2 = -1
            
            arr1 = np.append(arr1, self.truncate(a0, 4))
            bet_arr = np.append(bet_arr, projected_price)
            arr2 = np.append(arr2, self.truncate(np.abs(bet_arr[-1]), 4))
            
            close = arr1[-1]
            stopPriceBuy = close * .99 # Trigger stop limit when price falls 1%.
            stopPriceSell = close * 1.01 # Trigger stop limit when price falls 1%.
                
            if len(stockprices) > rsi_interval:
                _data_ = np.array(stockprices, float)
                rsi = ta.RSI(_data_.ravel(), timeperiod=rsi_interval)
                rsi = rsi[np.logical_not(np.isnan(rsi))][-1]
            else:
                return

            if len(weekly_stockprices_arr[ticker_idx]) > rsi_interval:
                _data_ = np.array(weekly_stockprices_arr[ticker_idx], float)
                rsi_intra_daily = ta.RSI(_data_.ravel(), timeperiod=rsi_interval)
                rsi_intra_daily = rsi_intra_daily[np.logical_not(np.isnan(rsi_intra_daily))][-1]
            else:
                rsi_intra_daily = 50

            rsi_intra_daily_array[ticker_idx] = np.append(rsi_intra_daily_array[ticker_idx], rsi_intra_daily)

            real = ta.MOM(stockprices, timeperiod=10)
            real = np.mean(real[np.logical_not(np.isnan(real))])

            prices = historical_train_data
            price_hist = historical_train_data[-240:]
            ma1 = np.mean(price_hist)
            price_hist = historical_train_data[-1200:]
            ma2 = np.mean(price_hist)
            
            start_bar = self.feature_window
            price_list = prices
            
            X = [] # list of feature sets
            y = [] # list of labels, one for each feature set
                
            bar = start_bar
                
            # feature creation
            while bar < len(price_list)-1:
                try:

                    end_price = price_list[bar+1] # "tomorrow"'s price'
                    begin_price = price_list[bar] # today's price
                    
                    pricing_list = []
                    xx = 0
                    for _ in range(self.feature_window):
                        price = price_list[bar-(self.feature_window-xx)]
                        pricing_list.append(price)
                        xx += 1
                    
                    # get the % change in daily prices of last 10 days
                    features = np.around(np.diff(pricing_list) / pricing_list[:-1] * 100.0, 1)
                    
                    # if tomorrow's price is more than today's price
                    # label the feature set (% change in last 10 days)
                    # a 1 (strong outlook, buy) else -1 (weak outlook, sell)
                    if end_price > begin_price:
                        label = 1
                    else:
                        label = -1

                    bar += 1
                    X.append(features)
                    y.append(label)
                    # print(features)

                except Exception as e:
                    bar += 1
                    print(('feature creation',str(e)))

            clf1 = RandomForestClassifier()
            clf2 = LinearSVC()
            ##clf3 = NuSVC()
            #clf3 = SVC()
            clf3 = OneClassSVM()
            clf4 = LogisticRegression()

            # now we get the prices and features for the last 10 days
            last_prices = price_list[-self.feature_window:]
            current_features = np.around(np.diff(last_prices) / last_prices[:-1] * 100.0, 1)

            # append the last 10 days feature set
            # scale the data (mean becomes zero, SD = 0), necessary for ML algo to work
            X.append(current_features)
            X = preprocessing.scale(np.reshape(X, (-1, 1)))

            # the current feature will be the last SCALED feature set
            # X will be all the feature sets, excluding the most recent one,
            # this is the feature set which we will be using to predict
            current_features = X[-1]
            X = X[:-1]
            
            if len(np.unique(np.reshape(y, (-1, 1)))) == 1:
                return

            # create {XGB Classification} model
            clf5 = xgb.XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
                colsample_bynode=1, colsample_bytree=1, eval_metric='mlogloss',
                gamma=0, gpu_id=-1, importance_type='gain',
                interaction_constraints='', learning_rate=0.300000012,
                max_delta_step=0, max_depth=6, min_child_weight=1, missing=1,
                monotone_constraints='()', n_estimators=100, n_jobs=16,
                num_parallel_tree=1, objective='binary:hinge', random_state=0,
                reg_alpha=0, reg_lambda=1, scale_pos_weight=None, subsample=1,
                tree_method='exact', use_label_encoder=False,
                validate_parameters=1, verbosity=None)

            from sklearn.preprocessing import LabelEncoder
            le = LabelEncoder()
            y_train = le.fit_transform(np.reshape(y, (-1, 1)))

            clf1.fit(X[-len(np.reshape(y, (-1, 1))):], np.reshape(y, (-1, 1)))
            clf2.fit(X[-len(np.reshape(y, (-1, 1))):], np.reshape(y, (-1, 1)))
            clf3.fit(X[-len(np.reshape(y, (-1, 1))):], np.reshape(y, (-1, 1)))
            clf4.fit(X[-len(np.reshape(y, (-1, 1))):], np.reshape(y, (-1, 1)))
            clf5.fit(X[-len(np.reshape(y, (-1, 1))):], y_train)

            p1 = clf1.predict(np.reshape(current_features, (-1, 1)))[0]
            p2 = clf2.predict(np.reshape(current_features, (-1, 1)))[0]
            p3 = clf3.predict(np.reshape(current_features, (-1, 1)))[0]
            p4 = clf4.predict(np.reshape(current_features, (-1, 1)))[0]
            p5 = clf5.predict(np.reshape(current_features, (-1, 1)))[0]

            if Counter([p1,p2,p3,p4,p5]).most_common(1)[0][1] >= no_ctr[ticker_idx]:
                p = Counter([p1,p2,p3,p4,p5]).most_common(1)[0][0]
            else:
                p = 0

            print(('ma1_d: ',ma1))
            print(('ma2_d :',ma2))
            print(('p1 :',p1))
            print(('p2 :',p2))
            print(('p3 :',p3))
            print(('p4 :',p4))
            print(('p5 :',p5))
            self.Debug('Prediction' + "\t" + str(p))

            if p == 1:
                t_indicator = +1
            elif p == -1:
                t_indicator = -1
            else:
                t_indicator = 0

            t_indicator_arr = np.append(t_indicator_arr, t_indicator)
    
            if trading_quantum == 0 or trading_quantum < 0.00000001:
                self.Log("Too low trade order size")
                            
                return

            if ticker == "BTCUSD":
                leverage = self.leverage_targets1
            elif ticker == "ETHUSD":
                leverage = self.leverage_targets2
            elif ticker == "BTCEUR":
                leverage = self.leverage_targets3
            elif ticker == "LTCUSD":
                leverage = self.leverage_targets4

            buying_power = self.Portfolio.MarginRemaining
            if buying_power <= 0:
                return

            if self.Transactions.GetOpenOrders(ticker):
                return

            if verbage == "HAMMER ":
                self.conf_swing_level = -1.0
            if verbage == "STAR ":
                self.conf_swing_level = +1.0
            if verbage == "MAJOR MOVE ":
                '''
                if mom_array[ticker_idx][-1] >= 0:
                    self.conf_swing_level = -1.0
                    self.SafeMarketOrder(ticker, leverage, tag="rebalance")
                    ticker_idx += 1
                    continue
                elif mom_array[ticker_idx][-1] < 0:
                    self.conf_swing_level = +1.0
                    self.SafeMarketOrder(ticker, +leverage, tag="rebalance")
                    ticker_idx += 1
                    continue
                '''
                self.conf_swing_level = 0.0
            if verbage == "GAP UP ":
                self.conf_swing_level = -1.0
            if verbage == "GAP DOWN ":
                self.conf_swing_level = +1.0
            if verbage == "BEARISH ENGULFING ":
                self.conf_swing_level = -1.0
            if verbage == "BULLISH ENGULFING ":
                self.conf_swing_level = +1.0
            if verbage == "PIERCING LINE ":
                '''
                if mom_array[ticker_idx][-1] >= 0:
                    self.SafeMarketOrder(ticker, +leverage, tag="rebalance")
                    ticker_idx += 1
                    continue
                elif mom_array[ticker_idx][-1] < 0:
                    self.SafeMarketOrder(ticker, leverage, tag="rebalance")
                    ticker_idx += 1
                    continue
                '''
                self.conf_swing_level = 0.0
            if verbage == "BLACK MARUBOZU ":
                self.conf_swing_level = +1.0
            if verbage == "WHITE MARUBOZU ":
                self.conf_swing_level = -1.0
            if verbage == "BEARISH DOJI ":
                self.conf_swing_level = -1.0
            if verbage == "BULLISH DOJI ":
                self.conf_swing_level = -1.0
            else:
                self.conf_swing_level = 0.0

            self.mom_arr = np.append(self.mom_arr, real1)
            mom_array[ticker_idx] = np.append(mom_array[ticker_idx], self.mom_arr[-1])

            if mode(t_indicator_arr[-1:]) == +1 and mom_array[ticker_idx][-1] >= 0 and rsi < 30 and projected_price >= np.max(a0_arr[-offset:]):
                sign = -1
            elif mode(t_indicator_arr[-1:]) == -1 and mom_array[ticker_idx][-1] < 0 and rsi > 70 and projected_price < np.min(a0_arr[-offset:]):
                sign = +1
            else:
                if rsi_intra_daily_array[ticker_idx][-1] < 30:
                    sign = -1
                elif rsi_intra_daily_array[ticker_idx][-1] > 70:
                    sign = 0
                else:
                    sign = +1

            if sign == -1 and mom_array[ticker_idx][-1] < 0 and rsi > 70:
                exp_factor = 1.0

                sign_ = +1

            if real2 >= 50 and real2 <= 60:
                exp_factor = 0.10

                sign_ = -1
            else:
                if real2 < 30:
                    exp_factor = 1.0

                    sign_ = +1
                elif real2 > 70:
                    exp_factor = 1.0

                    sign_ = -1

            t_indicator_arr_ = t_indicator_arr[-16:]
            count_minus1 = t_indicator_arr_[::-4].tolist().count(-1)
            count_zero = t_indicator_arr_[::-4].tolist().count(0)
            count_plus1 = t_indicator_arr_[::-4].tolist().count(+1)

            if count_minus1 == 4:
                sign__ = -1
            if count_zero == 4:
                sign__ = 0
            if count_plus1 == 4:
                sign__ = +1
            else:
                sign__ = +1

            sign = sign__ *sign_ *sign

            ____quantity = (exposure_risk_factor *(exp_factor *(0.5 *leverage)))
            _quantity = (exposure_risk_factor *(exp_factor *(0.33 *leverage)))
            __quantity = (exposure_risk_factor *(exp_factor *(leverage)))
            ___quantity = (exposure_risk_factor *(exp_factor *(0.42 *leverage)))

            if len(sign_inp_arr) > 10:
                try:
                    sign_dec_1 = self.ML_engine(sign_inp_arr)
                except:
                    sign_dec_1 = -sign

                sign_dec_2 = sign

                if sign_dec_1 != sign_dec_2:
                    sign = sign_dec_1

            if mom_array[ticker_idx][-1] > 0:
                _sign = -1
            else:
                _sign = +1
                
            sign = _sign * sign

            if enable_live_mode == True:
                if rsi < 30 and t_indicator == -1:
                    for ticker in self.tickers:
                        if ticker == "BTCUSD":
                            leverage = self.leverage_targets1
                        elif ticker == "ETHUSD":
                            leverage = self.leverage_targets2
                        elif ticker == "BTCEUR":
                            leverage = self.leverage_targets3
                        elif ticker == "LTCUSD":
                            leverage = self.leverage_targets4

                        if self.Portfolio.MarginRemaining < 50:
                            return
                        if self.Transactions.GetOpenOrders(ticker):
                            return
                        # place orders here
                    
                        self.SafeMarketOrder(ticker, +sign *leverage, tag="rebalance")
                elif rsi > 70 and t_indicator == +1:
                    for ticker in self.tickers:
                        if ticker == "BTCUSD":
                            leverage = self.leverage_targets1
                        elif ticker == "ETHUSD":
                            leverage = self.leverage_targets2
                        elif ticker == "BTCEUR":
                            leverage = self.leverage_targets3
                        elif ticker == "LTCUSD":
                            leverage = self.leverage_targets4

                        if self.Portfolio.MarginRemaining < 50:
                            return
                        if self.Transactions.GetOpenOrders(ticker):
                            return
                        # place orders here
                    
                        self.SafeMarketOrder(ticker, -sign *leverage, tag="rebalance")
                else:
                    self.Liquidate(ticker)
                
                    self.SetHoldings(ticker, 0)

            if self.Portfolio[ticker].UnrealizedProfit > 0 and self.Portfolio[ticker].UnrealizedProfit >= (profit_factor *self.Portfolio.TotalPortfolioValue):
                sign_inp_arr = np.append(sign_inp_arr, sign)

                exp_factor = 1.0

                sign_ = +1
                    
                self.Liquidate(ticker)
                
                self.SetHoldings(ticker, 0)
                
                self.Log("Liquidating..")

            ticker_idx += 1