diff --git a/Dockerfile b/Dockerfile index a5ef686..3cb3638 100644 --- a/Dockerfile +++ b/Dockerfile @@ -60,7 +60,7 @@ ENV NODE_ENV=demo # RUN apk update && apk add bash RUN apk update && apk add git -RUN npm install -g npm@latest +#RUN npm install -g npm@latest WORKDIR /app @@ -69,6 +69,7 @@ COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"] # && mv node_modules ../ COPY . . RUN npm install +#RUN mpm install nodemon EXPOSE 8080 8081 diff --git a/Niki/trader/test-NNFX/dealer.py b/Niki/trader/test-NNFX/dealer.py new file mode 100644 index 0000000..d67ab1f --- /dev/null +++ b/Niki/trader/test-NNFX/dealer.py @@ -0,0 +1,11 @@ +import ccxt +import pandas as pd +exchange = ccxt.coinbase() +symbol = 'BTC/USDT' +timeframe = '1m' +ohlcv = exchange.fetch_ohlcv(symbol, timeframe) +df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume']) +df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') +df.set_index('timestamp', inplace=True) +# print(df.head()) +print(df) \ No newline at end of file diff --git a/Niki/trader/test-NNFX/examples/exchanges.py b/Niki/trader/test-NNFX/examples/exchanges.py new file mode 100644 index 0000000..7a150b5 --- /dev/null +++ b/Niki/trader/test-NNFX/examples/exchanges.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- + +import os +import sys +from pprint import pprint + +root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +sys.path.append(root + '/python') + +import ccxt # noqa: E402 + + +print('CCXT Version:', ccxt.__version__) + +for exchange_id in ccxt.exchanges: + try: + exchange = getattr(ccxt, exchange_id)() + print(exchange_id) + # do what you want with this exchange + # pprint(dir(exchange)) + except Exception as e: + print(e) \ No newline at end of file diff --git a/Niki/trader/test-NNFX/strategy.pine b/Niki/trader/test-NNFX/strategy.pine new file mode 100644 index 0000000..9132d2f --- /dev/null +++ b/Niki/trader/test-NNFX/strategy.pine @@ -0,0 +1,99 @@ +//@version=5 +// https://www.youtube.com/watch?v=3fBLZgWSsy4 +strategy("NNFX Style Strategy with ADX, EMA, ATR SL and TP", overlay=true) + +// SSL Channel +period = input.int(title="SSL Period", defval=140) +smaHigh = ta.sma(high, period) +smaLow = ta.sma(low, period) +var float Hlv = na +Hlv := close > smaHigh ? 1 : close < smaLow ? -1 : nz(Hlv[1]) +sslDown = Hlv < 0 ? smaHigh : smaLow +sslUp = Hlv < 0 ? smaLow : smaHigh + +plot(sslDown, linewidth=2, color=color.red) +plot(sslUp, linewidth=2, color=color.lime) + +// T3 Indicator +length_fast = input.int(40, minval=1, title="Fast T3 Length") +length_slow = input.int(90, minval=1, title="Slow T3 Length") +b = 0.7 + +t3(x, length) => + e1 = ta.ema(x, length) + e2 = ta.ema(e1, length) + e3 = ta.ema(e2, length) + e4 = ta.ema(e3, length) + e5 = ta.ema(e4, length) + e6 = ta.ema(e5, length) + c1 = -b * b * b + c2 = 3 * b * b + 3 * b * b * b + c3 = -6 * b * b - 3 * b - 3 * b * b * b + c4 = 1 + 3 * b + b * b * b + 3 * b * b + c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3 + +t3_fast = t3(close, length_fast) +t3_slow = t3(close, length_slow) + +plot(t3_fast, color=color.blue, title="T3 Fast") +plot(t3_slow, color=color.red, title="T3 Slow") + +// ADX Calculation +adxlen = input.int(100, title="ADX Smoothing") +dilen = input.int(110, title="DI Length") + +dirmov(len) => + up = ta.change(high) + down = -ta.change(low) + plusDM = na(up) ? na : (up > down and up > 0 ? up : 0) + minusDM = na(down) ? na : (down > up and down > 0 ? down : 0) + truerange = ta.rma(ta.tr(true), len) + plus = nz(100 * ta.rma(plusDM, len) / truerange) + minus = nz(100 * ta.rma(minusDM, len) / truerange) + [plus, minus] + +adx(dilen, adxlen) => + [plus, minus] = dirmov(dilen) + sum = plus + minus + adx = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), adxlen) + adx + +adx_value = adx(dilen, adxlen) +adx_ema_length = input.int(80, title="ADX EMA Length") +adx_ema = ta.ema(adx_value, adx_ema_length) + +plot(adx_value, title="ADX", color=color.orange) +plot(adx_ema, title="ADX EMA", color=color.purple) + +// ATR-based Stop Loss and Take Profit +atr_length = input.int(120, title="ATR Length") +atr_stop_loss_multiplier = input.float(10, title="ATR Stop Loss Multiplier") +atr_take_profit_multiplier = input.float(20, title="ATR Take Profit Multiplier") +atr = ta.atr(atr_length) + +// Strategy Logic +longCondition = ta.crossover(t3_fast, t3_slow) and adx_value > adx_ema and Hlv > 0 +shortCondition = ta.crossunder(t3_fast, t3_slow) and adx_value > adx_ema and Hlv < 0 + +exitLongCondition = ta.crossunder(t3_fast, t3_slow) or Hlv < 0 +exitShortCondition = ta.crossover(t3_fast, t3_slow) or Hlv > 0 + +// Debug plots +plotshape(series=longCondition, location=location.belowbar, color=color.green, style=shape.labelup, text="LONG") +plotshape(series=shortCondition, location=location.abovebar, color=color.red, style=shape.labeldown, text="SHORT") + +if (longCondition) + stopLoss = close - atr_stop_loss_multiplier * atr + takeProfit = close + atr_take_profit_multiplier * atr + strategy.entry("Long", strategy.long) + strategy.exit("Long TP/SL", from_entry="Long", stop=stopLoss, limit=takeProfit) +if (shortCondition) + stopLoss = close + atr_stop_loss_multiplier * atr + takeProfit = close - atr_take_profit_multiplier * atr + strategy.entry("Short", strategy.short) + strategy.exit("Short TP/SL", from_entry="Short", stop=stopLoss, limit=takeProfit) + +if (exitLongCondition) + strategy.close("Long") +if (exitShortCondition) + strategy.close("Short") \ No newline at end of file diff --git a/Niki/trader/test-NNFX/strategy.py b/Niki/trader/test-NNFX/strategy.py new file mode 100644 index 0000000..f47f90c --- /dev/null +++ b/Niki/trader/test-NNFX/strategy.py @@ -0,0 +1,89 @@ +import numpy as np +import pandas as pd + +class NNFXStrategy: + def __init__(self, ssl_period=140, t3_fast_length=40, t3_slow_length=90, + adx_len=100, di_len=110, adx_ema_length=80, + atr_length=120, atr_stop_loss_multiplier=10, atr_take_profit_multiplier=20): + self.ssl_period = ssl_period + self.t3_fast_length = t3_fast_length + self.t3_slow_length = t3_slow_length + self.adx_len = adx_len + self.di_len = di_len + self.adx_ema_length = adx_ema_length + self.atr_length = atr_length + self.atr_stop_loss_multiplier = atr_stop_loss_multiplier + self.atr_take_profit_multiplier = atr_take_profit_multiplier + + def sma(self, series, period): + return series.rolling(window=period).mean() + + def t3(self, series, length, b=0.7): + e1 = series.ewm(span=length).mean() + e2 = e1.ewm(span=length).mean() + e3 = e2.ewm(span=length).mean() + e4 = e3.ewm(span=length).mean() + e5 = e4.ewm(span=length).mean() + e6 = e5.ewm(span=length).mean() + c1 = -b * b * b + c2 = 3 * b * b + 3 * b * b * b + c3 = -6 * b * b - 3 * b - 3 * b * b * b + c4 = 1 + 3 * b + b * b * b + 3 * b * b + return c1 * e6 + c2 * e5 + c3 * e4 + c4 * e3 + + def adx(self, high, low, close, di_len, adx_len): + plus_dm = high.diff().clip(lower=0) + minus_dm = low.diff().clip(upper=0).abs() + tr = np.maximum.reduce([high - low, (high - close.shift()).abs(), (low - close.shift()).abs()]) + atr = tr.rolling(window=di_len).mean() + plus_di = 100 * (plus_dm.rolling(window=di_len).mean() / atr) + minus_di = 100 * (minus_dm.rolling(window=di_len).mean() / atr) + dx = 100 * (plus_di - minus_di).abs() / (plus_di + minus_di) + adx = dx.rolling(window=adx_len).mean() + adx_ema = adx.ewm(span=self.adx_ema_length).mean() + return adx, adx_ema + + def atr(self, high, low, close, atr_length): + tr = np.maximum.reduce([high - low, (high - close.shift()).abs(), (low - close.shift()).abs()]) + return tr.rolling(window=atr_length).mean() + + def generate_signals(self, data): + data['sma_high'] = self.sma(data['high'], self.ssl_period) + data['sma_low'] = self.sma(data['low'], self.ssl_period) + data['hlv'] = np.where(data['close'] > data['sma_high'], 1, np.where(data['close'] < data['sma_low'], -1, np.nan)) + data['hlv'] = data['hlv'].ffill().fillna(0) + data['ssl_down'] = np.where(data['hlv'] < 0, data['sma_high'], data['sma_low']) + data['ssl_up'] = np.where(data['hlv'] < 0, data['sma_low'], data['sma_high']) + + data['t3_fast'] = self.t3(data['close'], self.t3_fast_length) + data['t3_slow'] = self.t3(data['close'], self.t3_slow_length) + + data['adx'], data['adx_ema'] = self.adx(data['high'], data['low'], data['close'], self.di_len, self.adx_len) + + data['atr'] = self.atr(data['high'], data['low'], data['close'], self.atr_length) + + data['long_condition'] = (data['t3_fast'] > data['t3_slow']) & (data['adx'] > data['adx_ema']) & (data['hlv'] > 0) + data['short_condition'] = (data['t3_fast'] < data['t3_slow']) & (data['adx'] > data['adx_ema']) & (data['hlv'] < 0) + + data['exit_long_condition'] = (data['t3_fast'] < data['t3_slow']) | (data['hlv'] < 0) + data['exit_short_condition'] = (data['t3_fast'] > data['t3_slow']) | (data['hlv'] > 0) + + return data + + def apply_strategy(self, data): + data = self.generate_signals(data) + trades = [] + for i in range(1, len(data)): + if data['long_condition'].iloc[i]: + stop_loss = data['close'].iloc[i] - self.atr_stop_loss_multiplier * data['atr'].iloc[i] + take_profit = data['close'].iloc[i] + self.atr_take_profit_multiplier * data['atr'].iloc[i] + trades.append(('long', data.index[i], stop_loss, take_profit)) + elif data['short_condition'].iloc[i]: + stop_loss = data['close'].iloc[i] + self.atr_stop_loss_multiplier * data['atr'].iloc[i] + take_profit = data['close'].iloc[i] - self.atr_take_profit_multiplier * data['atr'].iloc[i] + trades.append(('short', data.index[i], stop_loss, take_profit)) + elif data['exit_long_condition'].iloc[i]: + trades.append(('exit_long', data.index[i])) + elif data['exit_short_condition'].iloc[i]: + trades.append(('exit_short', data.index[i])) + return trades diff --git a/_doc/_notes/readme.md b/_doc/_notes/readme.md new file mode 100644 index 0000000..c3f9f72 --- /dev/null +++ b/_doc/_notes/readme.md @@ -0,0 +1,4 @@ +start the project in container: +# +#for debugging: +# docker-compose -f docker-compose.debug.yml up diff --git a/docker-compose.debug.yml b/docker-compose.debug.yml index a3107c4..0f229c0 100644 --- a/docker-compose.debug.yml +++ b/docker-compose.debug.yml @@ -8,7 +8,13 @@ services: dockerfile: ./Dockerfile environment: NODE_ENV: development + # TTS_BACKEND_URL: https://tts.d-popov.com/asr + TTS_BACKEND_URL: http://192.168.0.10:9009/asr + WS_URL: wss://ws.ai.d-popov.com + SERVER_PORT_WS: 3001 + SERVER_PORT_HTTP: 3000 ports: - - 3000:3000 + - 23000:3000 + - 23001:3001 - 9229:9229 command: ["node", "--inspect=0.0.0.0:9229", "web/server.js"]