diff --git a/.drone.yml b/.drone.yml index e0971c8..848702d 100644 --- a/.drone.yml +++ b/.drone.yml @@ -13,4 +13,6 @@ steps: registry: harbor.frantchenco.page auto_tag: true tags: - - latest \ No newline at end of file + - latest + cache_from: + - "harbor.frantchenco.page/library/gekko" \ No newline at end of file diff --git a/deployment_traefix_ingressroute.yaml b/deployment_traefix_ingressroute.yaml index e69de29..7a730ab 100644 --- a/deployment_traefix_ingressroute.yaml +++ b/deployment_traefix_ingressroute.yaml @@ -0,0 +1,23 @@ +apiVersion: traefik.containo.us/v1alpha1 +kind: Middleware +metadata: + name: svc-rancher-headers +spec: + headers: + customRequestHeaders: + X-Forwarded-Proto: "https" +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: ingressroutetls-gekko + namespace: gekko +spec: + entryPoints: + - websecure + routes: + - match: Host(`gekko.dev.frantchenco.page`) + kind: Rule + services: + - name: gekko + port: 3000 diff --git a/sample-config.js b/sample-config.js deleted file mode 100644 index 34c5092..0000000 --- a/sample-config.js +++ /dev/null @@ -1,539 +0,0 @@ -// Everything is explained here: -// @link https://gekko.wizb.it/docs/commandline/plugins.html - -var config = {}; - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// GENERAL SETTINGS -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -config.debug = true; // for additional logging / debugging - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// WATCHING A MARKET -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -config.watch = { - - // see https://gekko.wizb.it/docs/introduction/supported_exchanges.html - exchange: 'binance', - currency: 'USDT', - asset: 'BTC', -} - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CONFIGURING TRADING ADVICE -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -config.tradingAdvisor = { - enabled: true, - method: 'MACD', - candleSize: 60, - historySize: 10, -} - -// MACD settings: -config.MACD = { - // EMA weight (α) - // the higher the weight, the more smooth (and delayed) the line - short: 10, - long: 21, - signal: 9, - // the difference between the EMAs (to act as triggers) - thresholds: { - down: -0.025, - up: 0.025, - // How many candle intervals should a trend persist - // before we consider it real? - persistence: 1 - } -}; - -// settings for other strategies can be found at the bottom, note that only -// one strategy is active per gekko, the other settings are ignored. - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CONFIGURING PLUGINS -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -// do you want Gekko to simulate the profit of the strategy's own advice? -config.paperTrader = { - enabled: true, - // report the profit in the currency or the asset? - reportInCurrency: true, - // start balance, on what the current balance is compared with - simulationBalance: { - // these are in the unit types configured in the watcher. - asset: 1, - currency: 100, - }, - // how much fee in % does each trade cost? - feeMaker: 0.15, - feeTaker: 0.25, - feeUsing: 'maker', - // how much slippage/spread should Gekko assume per trade? - slippage: 0.05, -} - -config.performanceAnalyzer = { - enabled: true, - riskFreeReturn: 5 -} - -// Want Gekko to perform real trades on buy or sell advice? -// Enabling this will activate trades for the market being -// watched by `config.watch`. -config.trader = { - enabled: false, - key: '', - secret: '', - username: '', // your username, only required for specific exchanges. - passphrase: '', // GDAX, requires a passphrase. -} - -config.eventLogger = { - enabled: false, - // optionally pass a whitelist of events to log, if not past - // the eventLogger will log _all_ events. - // whitelist: ['portfolioChange', 'portfolioValueChange'] -} - -config.pushover = { - enabled: false, - sendPushoverOnStart: false, - muteSoft: true, // disable advice printout if it's soft - tag: '[GEKKO]', - key: '', - user: '' -} - -config.blotter = { - enabled: false, - filename: 'blotter.csv', - dateFormat: 'l LT', - timezone: -300, // -300 minutes for EST(-5:00), only used if exchange doesn't provide correct timezone -} - -// want Gekko to send a mail on buy or sell advice? -config.mailer = { - enabled: false, // Send Emails if true, false to turn off - sendMailOnStart: true, // Send 'Gekko starting' message if true, not if false - - email: '', // Your Gmail address - muteSoft: true, // disable advice printout if it's soft - - // You don't have to set your password here, if you leave it blank we will ask it - // when Gekko's starts. - // - // NOTE: Gekko is an open source project < https://github.com/askmike/gekko >, - // make sure you looked at the code or trust the maintainer of this bot when you - // fill in your email and password. - // - // WARNING: If you have NOT downloaded Gekko from the github page above we CANNOT - // guarantuee that your email address & password are safe! - - password: '', // Your Gmail Password - if not supplied Gekko will prompt on startup. - - tag: '[GEKKO] ', // Prefix all email subject lines with this - - // ADVANCED MAIL SETTINGS - // you can leave those as is if you - // just want to use Gmail - - server: 'smtp.gmail.com', // The name of YOUR outbound (SMTP) mail server. - smtpauth: true, // Does SMTP server require authentication (true for Gmail) - // The following 3 values default to the Email (above) if left blank - user: '', // Your Email server user name - usually your full Email address 'me@mydomain.com' - from: '', // 'me@mydomain.com' - to: '', // 'me@somedomain.com, me@someotherdomain.com' - ssl: true, // Use SSL (true for Gmail) - port: '', // Set if you don't want to use the default port -} - -config.pushbullet = { - // sends pushbullets if true - enabled: false, - // Send 'Gekko starting' message if true - sendMessageOnStart: true, - // Send Message for advice? Recommend Flase for paper, true for live - sendOnAdvice: true, - // Send Message on Trade Completion? - sendOnTrade: true, - // For Overall P/L calc. Pass in old balance if desired, else leave '0' - startingBalance: 0, - // your pushbullet API key - key: '', - // your email - email: 'jon_snow@westeros.com', - // Messages will start with this tag - tag: '[GEKKO]' -}; - -config.kodi = { - // if you have a username & pass, add it like below - // http://user:pass@ip-or-hostname:8080/jsonrpc - host: 'http://ip-or-hostname:8080/jsonrpc', - enabled: false, - sendMessageOnStart: true, -} - -config.ircbot = { - enabled: false, - emitUpdates: false, - muteSoft: true, - channel: '#your-channel', - server: 'irc.freenode.net', - botName: 'gekkobot' -} - -config.telegrambot = { - enabled: false, - // Receive notifications for trades and warnings/errors related to trading - emitTrades: false, - token: 'YOUR_TELEGRAM_BOT_TOKEN', -}; - -config.twitter = { - // sends pushbullets if true - enabled: false, - // Send 'Gekko starting' message if true - sendMessageOnStart: false, - // disable advice printout if it's soft - muteSoft: false, - tag: '[GEKKO]', - // twitter consumer key - consumer_key: '', - // twitter consumer secret - consumer_secret: '', - // twitter access token key - access_token_key: '', - // twitter access token secret - access_token_secret: '' -}; - -config.xmppbot = { - enabled: false, - emitUpdates: false, - client_id: 'jabber_id', - client_pwd: 'jabber_pw', - client_host: 'jabber_server', - client_port: 5222, - status_msg: 'I\'m online', - receiver: 'jabber_id_for_updates' -} - -config.campfire = { - enabled: false, - emitUpdates: false, - nickname: 'Gordon', - roomId: null, - apiKey: '', - account: '' -} - -config.redisBeacon = { - enabled: false, - port: 6379, // redis default - host: '127.0.0.1', // localhost - // On default Gekko broadcasts - // events in the channel with - // the name of the event, set - // an optional prefix to the - // channel name. - channelPrefix: '', - broadcast: [ - 'candle' - ] -} - -config.slack = { - enabled: false, - token: '', - sendMessageOnStart: true, - muteSoft: true, - channel: '' // #tradebot -} - -config.ifttt = { - enabled: false, - eventName: 'gekko', - makerKey: '', - muteSoft: true, - sendMessageOnStart: true -} - -config.candleWriter = { - enabled: true -} - -config.adviceWriter = { - enabled: false, - muteSoft: true, -} - -config.backtestResultExporter = { - enabled: false, - writeToDisk: false, - data: { - stratUpdates: false, - portfolioValues: true, - stratCandles: true, - roundtrips: true, - trades: true - } -} - -config.candleUploader = { - enabled: false, - url: '', - apiKey: '' -} - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CONFIGURING ADAPTER -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -config.adapter = 'sqlite'; - -config.sqlite = { - path: 'plugins/sqlite', - - dataDirectory: 'history', - version: 0.1, - - journalMode: require('./web/isWindows.js') ? 'DELETE' : 'WAL', - - dependencies: [] -} - -// Postgres adapter example config (please note: requires postgres >= 9.5): -config.postgresql = { - path: 'plugins/postgresql', - version: 0.1, - connectionString: 'postgres://user:pass@localhost:5432', // if default port - database: null, // if set, we'll put all tables into a single database. - schema: 'public', - dependencies: [{ - module: 'pg', - version: '7.4.3' - }] -} - -// Mongodb adapter, requires mongodb >= 3.3 (no version earlier tested) -config.mongodb = { - path: 'plugins/mongodb', - version: 0.1, - connectionString: 'mongodb://localhost/gekko', // connection to mongodb server - dependencies: [{ - module: 'mongojs', - version: '2.4.0' - }] -} - -config.candleUploader = { - enabled: false, - url: '', - apiKey: '' -} - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CONFIGURING BACKTESTING -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -// Note that these settings are only used in backtesting mode, see here: -// @link: https://gekko.wizb.it/docs/commandline/backtesting.html - -config.backtest = { - daterange: 'scan', - // daterange: { - // from: "2018-03-01", - // to: "2018-04-28" - //}, - batchSize: 50 -} - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CONFIGURING IMPORTING -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -config.importer = { - daterange: { - // NOTE: these dates are in UTC - from: "2017-11-01 00:00:00", - to: "2017-11-20 00:00:00" - } -} - - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// OTHER STRATEGY SETTINGS -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -// Exponential Moving Averages settings: -config.DEMA = { - // EMA weight (α) - // the higher the weight, the more smooth (and delayed) the line - weight: 21, - // amount of candles to remember and base initial EMAs on - // the difference between the EMAs (to act as triggers) - thresholds: { - down: -0.025, - up: 0.025 - } -}; - -// PPO settings: -config.PPO = { - // EMA weight (α) - // the higher the weight, the more smooth (and delayed) the line - short: 12, - long: 26, - signal: 9, - // the difference between the EMAs (to act as triggers) - thresholds: { - down: -0.025, - up: 0.025, - // How many candle intervals should a trend persist - // before we consider it real? - persistence: 2 - } -}; - -// Uses one of the momentum indicators but adjusts the thresholds when PPO is bullish or bearish -// Uses settings from the ppo and momentum indicator config block -config.varPPO = { - momentum: 'TSI', // RSI, TSI or UO - thresholds: { - // new threshold is default threshold + PPOhist * PPOweight - weightLow: 120, - weightHigh: -120, - // How many candle intervals should a trend persist - // before we consider it real? - persistence: 0 - } -}; - -// RSI settings: -config.RSI = { - interval: 14, - thresholds: { - low: 30, - high: 70, - // How many candle intervals should a trend persist - // before we consider it real? - persistence: 1 - } -}; - -// TSI settings: -config.TSI = { - short: 13, - long: 25, - thresholds: { - low: -25, - high: 25, - // How many candle intervals should a trend persist - // before we consider it real? - persistence: 1 - } -}; - -// Ultimate Oscillator Settings -config.UO = { - first: { - weight: 4, - period: 7 - }, - second: { - weight: 2, - period: 14 - }, - third: { - weight: 1, - period: 28 - }, - thresholds: { - low: 30, - high: 70, - // How many candle intervals should a trend persist - // before we consider it real? - persistence: 1 - } -}; - -// CCI Settings -config.CCI = { - constant: 0.015, // constant multiplier. 0.015 gets to around 70% fit - history: 90, // history size, make same or smaller than history - thresholds: { - up: 100, // fixed values for overbuy upward trajectory - down: -100, // fixed value for downward trajectory - persistence: 0 // filter spikes by adding extra filters candles - } -}; - -// StochRSI settings -config.StochRSI = { - interval: 3, - thresholds: { - low: 20, - high: 80, - // How many candle intervals should a trend persist - // before we consider it real? - persistence: 3 - } -}; - - -// custom settings: -config.custom = { - my_custom_setting: 10, -} - -config['talib-macd'] = { - parameters: { - optInFastPeriod: 10, - optInSlowPeriod: 21, - optInSignalPeriod: 9 - }, - thresholds: { - down: -0.025, - up: 0.025, - } -} - -config['talib-macd'] = { - parameters: { - optInFastPeriod: 10, - optInSlowPeriod: 21, - optInSignalPeriod: 9 - }, - thresholds: { - down: -0.025, - up: 0.025, - } -} - -config['tulip-adx'] = { - optInTimePeriod: 10, - thresholds: { - down: -0.025, - up: 0.025, - } -} - - -// set this to true if you understand that Gekko will -// invest according to how you configured the indicators. -// None of the advice in the output is Gekko telling you -// to take a certain position. Instead it is the result -// of running the indicators you configured automatically. -// -// In other words: Gekko automates your trading strategies, -// it doesn't advice on itself, only set to true if you truly -// understand this. -// -// Not sure? Read this first: https://github.com/askmike/gekko/issues/201 -config['I understand that Gekko only automates MY OWN trading strategies'] = false; - -module.exports = config; \ No newline at end of file diff --git a/strategies/frantche-MACD-RSI.js b/strategies/frantche-MACD-RSI.js new file mode 100644 index 0000000..7454ef7 --- /dev/null +++ b/strategies/frantche-MACD-RSI.js @@ -0,0 +1,140 @@ +/* + + Frantche MACD RSI - DJM 14/06/2021 + + (updated a couple of times since, check git history) + + */ + +// helpers +var _ = require('lodash'); +var log = require('../core/log.js'); + + +// let's create our own method +var method = {}; + +// prepare everything our method needs +method.init = function() { + // keep state about the current trend + // here, on every new candle we use this + // state object to check if we need to + // report it. + this.trend = { + direction: 'none', + duration: 0, + persisted: false, + adviced: false + }; + + log.debug(this.settings); + + + // how many candles do we need as a base + // before we can start giving advice? + this.requiredHistory = this.tradingAdvisor.historySize; + + // define the indicators we need + this.addIndicator('macd', 'MACD', this.settings); + this.addIndicator('rsi', 'RSI', this.settings); + +} + +// what happens on every new candle? +method.update = function(candle) { + // nothing! +} + +// for debugging purposes: log the last calculated +// EMAs and diff. +method.log = function() { + var digits = 8; + var macd = this.indicators.macd; + + var diff = macd.diff; + var signal = macd.signal.result; + + log.debug('calculated MACD properties for candle:'); + log.debug('\t', 'short:', macd.short.result.toFixed(digits)); + log.debug('\t', 'long:', macd.long.result.toFixed(digits)); + log.debug('\t', 'macd:', diff.toFixed(digits)); + log.debug('\t', 'signal:', signal.toFixed(digits)); + log.debug('\t', 'macdiff:', macd.result.toFixed(digits)); +} + +method.check = function() { + var macddiff = this.indicators.macd.result; + + if(macddiff > this.settings.thresholds.up) { + + // new trend detected + if(this.trend.direction !== 'up') + // reset the state for the new trend + this.trend = { + duration: 0, + persisted: false, + direction: 'up', + adviced: false + }; + + this.trend.duration++; + + log.debug('In uptrend since', this.trend.duration, 'candle(s)'); + + if(this.trend.duration >= this.settings.thresholds.persistence) + this.trend.persisted = true; + + if(this.trend.persisted && !this.trend.adviced) { + this.trend.adviced = true; + this.advice('long'); + } else + this.advice(); + + } else if(macddiff < this.settings.thresholds.down) { + + // new trend detected + if(this.trend.direction !== 'down') + // reset the state for the new trend + this.trend = { + duration: 0, + persisted: false, + direction: 'down', + adviced: false + }; + + this.trend.duration++; + + log.debug('In downtrend since', this.trend.duration, 'candle(s)'); + + if(this.trend.duration >= this.settings.thresholds.persistence) + this.trend.persisted = true; + + if(this.trend.persisted && !this.trend.adviced) { + this.trend.adviced = true; + this.advice('short'); + } else + this.advice(); + + } else { + + log.debug('In no trend'); + + // we're not in an up nor in a downtrend + // but for now we ignore sideways trends + // + // read more @link: + // + // https://github.com/askmike/gekko/issues/171 + + // this.trend = { + // direction: 'none', + // duration: 0, + // persisted: false, + // adviced: false + // }; + + this.advice(); + } +} + +module.exports = method; diff --git a/web/baseUIconfig.js b/web/baseUIconfig.js index 1acb922..fb04ef1 100644 --- a/web/baseUIconfig.js +++ b/web/baseUIconfig.js @@ -7,7 +7,8 @@ const CONFIG = { headless: false, api: { - host: '127.0.0.1', + host: 'localhost', + path: '/', port: 3000, timeout: 120000 // 2 minutes },