Merge branch 'master' of https://git.d-popov.com/popov/ai-kevin
This commit is contained in:
commit
49edcd4985
@ -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
|
||||
|
||||
|
||||
|
11
Niki/trader/test-NNFX/dealer.py
Normal file
11
Niki/trader/test-NNFX/dealer.py
Normal file
@ -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)
|
22
Niki/trader/test-NNFX/examples/exchanges.py
Normal file
22
Niki/trader/test-NNFX/examples/exchanges.py
Normal file
@ -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)
|
99
Niki/trader/test-NNFX/strategy.pine
Normal file
99
Niki/trader/test-NNFX/strategy.pine
Normal file
@ -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")
|
89
Niki/trader/test-NNFX/strategy.py
Normal file
89
Niki/trader/test-NNFX/strategy.py
Normal file
@ -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
|
4
_doc/_notes/readme.md
Normal file
4
_doc/_notes/readme.md
Normal file
@ -0,0 +1,4 @@
|
||||
start the project in container:
|
||||
#
|
||||
#for debugging:
|
||||
# docker-compose -f docker-compose.debug.yml up
|
@ -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"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user