Bitcoin TradingBot with Nightshark and Kraken

This blog post is about Trading automation in kraken using Nightshark.

SETUP:

AttributesDescriptions
Area[1]Signal over Tradingview Layout
Point.aBUY button on Kraken
Point.bSELL button on Kraken
Point.cSome random point in Kraken Layout

Nightshark Code:

StopScript() {
    Send, {F2}
}

BUY_condition() {
    global
    return (area[1] ~= "BUY")
}
SELL_condition() {
    global
    return (area[1] ~= "SELL")
}


loop {
    loop{
    read_areas()
    } until (BUY_condition())

    click(point.a)
    click(point.c)

    loop{
    read_areas()
    } until (SELL_condition())

    click(point.b)
    click(point.c)
}

TradingView Code:

//@version=6
indicator("Machine Learning Moving Average [LuxAlgo]", "LuxAlgo - Machine Learning Moving Average", overlay=true)
//---------------------------------------------------------------------------------------------------------------------
// Settings
//---------------------------------------------------------------------------------------------------------------------
window   = input.int(100, minval=0)
forecast = input.int(0)
sigma    = input.float(0.01, step=0.1, minval=0)

mult = input.float(2, 'Multiplicative Factor', minval=0)
src  = input.source(close, 'Source')

// Style
upCss   = input.color(color.new(#5b9cf6, 50), 'Upper Extremity', group='Style')
dnCss   = input.color(color.new(#e91e63, 50), 'Lower Extremity', group='Style')

bullCss = input.color(#3179f5, 'Moving Average', inline='ma', group='Style')
bearCss = input.color(#e91e63, '', inline='ma', group='Style')

//---------------------------------------------------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------------------------------------------------
rbf(x1, x2, l) => math.exp(-math.pow(x1 - x2, 2) / (2.0 * math.pow(l, 2)))

kernel_matrix(X1, X2, l) =>
    km = matrix.new<float>(array.size(X1), array.size(X2))

    i = 0
    for x1 in X1
        j = 0
        for x2 in X2
            rbf_val = rbf(x1, x2, l)
            matrix.set(km, i, j, rbf_val)
            j += 1
        i += 1
    km

//---------------------------------------------------------------------------------------------------------------------
// Kernel Setup
//---------------------------------------------------------------------------------------------------------------------
var identity = matrix.new<int>(window, window, 0)
var K_row = array.new_float(0)

if barstate.isfirst
    var xtrain = array.new_int(0)
    var xtest  = array.new_int(0)

    // Build identity matrix and training array
    for i = 0 to window - 1
        for j = 0 to window - 1
            matrix.set(identity, i, j, i == j ? 1 : 0)
        array.push(xtrain, i)

    // Build testing array
    for i = 0 to window + forecast - 1
        array.push(xtest, i)

    // Compute kernel matrices
    s      = matrix.mult(identity, sigma * sigma)
    Ktrain = matrix.sum(kernel_matrix(xtrain, xtrain, window), s)
    K_inv  = matrix.pinv(Ktrain)
    K_star = kernel_matrix(xtrain, xtest, window)
    // Multiply the transpose of K_star by K_inv and get the (window+forecast-1)th row as an array
    K_row_temp = matrix.row(matrix.mult(matrix.transpose(K_star), K_inv), window + forecast - 1)
    // Copy the computed row to K_row
    for i = 0 to array.size(K_row_temp) - 1
        array.push(K_row, array.get(K_row_temp, i))

//---------------------------------------------------------------------------------------------------------------------
// Moving Average Calculation
//---------------------------------------------------------------------------------------------------------------------
var os = 0

mean = ta.sma(src, window)

// Get end point estimate
var float out = na

if bar_index > window
    dotprod = 0.0
    // Dot product between last K_row and training data
    for i = 0 to window - 1
        dotprod += array.get(K_row, i) * (src[window - 1 - i] - mean)
    // Output
    out := dotprod + mean

mae   = ta.sma(math.abs(src - out), window) * mult
upper = out + mae
lower = out - mae

os := close > upper and out > out[1] ? 1 : close < lower and out < out[1] ? 0 : os

//---------------------------------------------------------------------------------------------------------------------
// Plotting
//---------------------------------------------------------------------------------------------------------------------
plot_out = plot(out, 'End Point GPR', color = os == 1 ? bullCss : bearCss)
plot_change = plot(os != os[1] ? out : na, 'Circle', color = os == 1 ? bullCss : bearCss, linewidth = 3, style = plot.style_circles)
plot_upper  = plot(upper, 'Upper', color = na)
plot_lower  = plot(lower, 'Lower', color = na)

fill(plot_upper, plot_out, out + mae, out, upCss, color.new(chart.bg_color, 100))
fill(plot_out, plot_lower, out, out - mae, color.new(chart.bg_color, 100), dnCss)

//---------------------------------------------------------------------------------------------------------------------
// Table Setup
//---------------------------------------------------------------------------------------------------------------------
// Create a table with 2 columns and 1 row in the top-right corner
var table signalTable = table.new(position.top_right, 2, 1, border_width = 1, frame_color = color.black)

// Determine the signal text
signalText = close > upper and out > out[1] ? "BUY" : close < lower and out < out[1] ? "SELL" : "NONE"

// Set background color: green for BUY, red for SELL, white for NONE
bgColor    = close > upper and out > out[1] ? color.green : close < lower and out < out[1] ? color.red : color.white

// Set text color: white for BUY/SELL, black for NONE
textColor  = close > upper and out > out[1] ? color.white : close < lower and out < out[1] ? color.white : color.black

// Update table cells on every bar
table.cell(signalTable, 0, 0, "SIGNAL", text_color = color.white, text_size = size.large, bgcolor = color.gray)
table.cell(signalTable, 1, 0, signalText, text_color = textColor, text_size = size.large, bgcolor = bgColor)
10
Subscribe to my newsletter

Read articles from ProcessOverProfit directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ProcessOverProfit
ProcessOverProfit