Repository: tommiehansen/gekko_tools Branch: master Commit: 35e9f81febfe Files: 26 Total size: 50.7 KB Directory structure: gitextract_1m361evv/ ├── .gitignore ├── cli/ │ ├── config.sample.sh │ ├── download.sh │ ├── imports/ │ │ ├── Compatibility/ │ │ │ ├── bash/ │ │ │ │ └── array.bash │ │ │ ├── compatibility.sh │ │ │ ├── default/ │ │ │ │ └── array.sh │ │ │ └── zsh/ │ │ │ └── array.zsh │ │ ├── colorizer.sh │ │ └── common.sh │ ├── lastupload/ │ │ └── last.txt │ └── upload.sh ├── strategies/ │ ├── RSI_BULL_BEAR.js │ ├── RSI_BULL_BEAR.toml │ ├── RSI_BULL_BEAR_ADX.js │ ├── RSI_BULL_BEAR_ADX.toml │ ├── TEMA.js │ └── TEMA.toml ├── syncAll/ │ ├── config.sample.sh │ ├── download.sh │ ├── sync/ │ │ └── last.txt │ └── upload.sh ├── temp/ │ ├── system/ │ │ ├── functions.php │ │ └── user.config.sample.php │ └── test.php └── wsl-install/ ├── gekko_install.sh └── readme.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ gitpush.sh *.tar *.gz cli/config.sh syncAll/config.sh user.config.php ================================================ FILE: cli/config.sample.sh ================================================ #!/bin/bash # Gekko directory # Relative -or- absolute to where you have gekko tools installed gekkoDir='../../gekko' ================================================ FILE: cli/download.sh ================================================ #!/bin/bash clear # ------------------------------ # # Download sync files @ lastupload/last.txt # ...and replace files in Gekko # # ------------------------------- # imports source imports/common.sh source imports/colorizer.sh # check config.sh if [ ! -f config.sh ]; then colorize "ERROR config.sh could not be found, copy config.sample.sh and modify to suit your needs!\n" return fi # check if last.txt file exist if [ ! -f lastupload/last.txt ]; then colorize "ERROR last.txt could not be found under lastupload so there's nothing to download.\n" return fi # import user config source config.sh outputDir="lastupload" file=$(cat $outputDir/last.txt) saveFile="$outputDir/sync.tar.gz"; # get $filename function get() { if [ $# -eq 0 ]; then echo -e "No arguments specified."; return 1; fi echo echo curl "$1" >> $saveFile; } # get the file colorize "Downloading $file, please stand by...." get $file printf "\n\n" # untar colorize "Unpacking $saveFile...\n" tar -xvzf $saveFile echo # sync new > old (and replace) colorize "Replacing old with new @ $gekkoDir/history\n" rsync -ah gekko/* $gekkoDir echo # remove crap rm -rf gekko rm -rf "$outputDir/sync.tar.gz" colorize "Completed.\n" ================================================ FILE: cli/imports/Compatibility/bash/array.bash ================================================ #### # Copyright (c) 2012, Jakob Westhoff # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #### # # This file does include a generic compatibility layer for accessing arrays in # bash. # #### ## # Define a variable as an empty array # # The variable should already exist in the scope you want to use it in # # @param name ## ARRAY_define() { local name="${1}" eval "${name}=()" } ## # Get the current amount of entries inside an existing array # # @param name ## ARRAY_count() { local name="${1}" if [ -z "$(set +u; eval "echo \"\${${name}}\"")" ]; then echo "0" else eval "echo \"\${#${name}[@]}\"" fi } ## # Get a certain index stored inside an array # # The index is zero based. The first entry entry is therefore supposed to be 0. # If the used shell does only provide 1-based arrays this needs to be mapped # inside of this function accordingly # # @param name # @param index ## ARRAY_get() { local name="${1}" local index="${2}" eval "echo \"\${${name}[${index}]}\"" } ## # Set a certain value stored to a certain index inside an array # # The index is zero based. The first entry entry is therefore supposed to be 0. # If the used shell does only provide 1-based arrays this needs to be mapped # inside of this function accordingly # # @param name # @param index # @param value ## ARRAY_set() { local name="${1}" local index="${2}" local value="${3}" eval "${name}[${index}]=\"${value}\"" } ## # Push a given value to the end of the provided array name # # @param name # @param value ## ARRAY_push() { local name="${1}" local value="${2}" eval "${name}[\${#${name}[@]}]=\"${value}\"" } ## # Peek at a value from the end of the provided array name without removing it # # @param name ## ARRAY_peek() { local name="${1}" eval "echo \"\${${name}[\${#${name}[@]}-1]}\"" } ## # Pop a value from the end of the provided array name # # @param name ## ARRAY_pop() { local name="${1}" echo "$(ARRAY_peek "${name}")" eval "unset \"${name}[\${#${name}[@]}-1]\"" } ## # Unset a certain index from the given array # # @param name ## ARRAY_unset() { local name="${1}" local index="${2}" eval "unset ${name}[${index}]" } ================================================ FILE: cli/imports/Compatibility/compatibility.sh ================================================ #### # Copyright (c) 2012, Jakob Westhoff # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #### # # This file does include generic entrypoint to the compatibility library, which # loads the compatibility layer for your currently used shell # #### if [ -n "${BASH_VERSION}" ]; then source "$( cd "$( dirname "${BASH_SOURCE}" )" && pwd )/bash/"*.bash elif [ -n "${ZSH_VERSION}" ]; then source "$( cd "$( dirname "${0}" )" && pwd )/zsh/"*.zsh else source "${COLORIZE_SH_SOURCE_DIR}/Compatibility/default/"*.sh fi ================================================ FILE: cli/imports/Compatibility/default/array.sh ================================================ #### # Copyright (c) 2013, Florian Sowade # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #### # # This file does include a generic compatibility layer for accessing arrays in # any POSIX shell. # #### ## # Define a variable as an empty array # # The variable should already exist in the scope you want to use it in # # @param name ## ARRAY_define() { local name="${1}" eval "${name}_COUNT=0" } ## # Get the current amount of entries inside an existing array # # @param name ## ARRAY_count() { local name="${1}" eval "echo \"\${${name}_COUNT}\"" } ## # Push a given value to the end of the provided array name # # @param name # @param value ## ARRAY_push() { local name="${1}" local value="${2}" local index="$(ARRAY_count "${name}")" eval "${name}_${index}='${value}'" eval "${name}_COUNT=$(( ${index} + 1 ))" } ## # Peek at a value from the end of the provided array name without removing it # # @param name ## ARRAY_peek() { local name="${1}" local index="$(( $(ARRAY_count "${name}") - 1 ))" eval "echo \"\${${name}_${index}}\"" } ## # Pop a value from the end of the provided array name # # @param name ## ARRAY_pop() { local name="${1}" local index="$(( $(ARRAY_count "${name}") - 1 ))" eval "echo \"\${${name}_${index}}\"" eval "${name}_COUNT=${index}" eval "unset ${name}_${index}" } ================================================ FILE: cli/imports/Compatibility/zsh/array.zsh ================================================ #### # Copyright (c) 2012, Jakob Westhoff # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #### # # This file does include a generic compatibility layer for accessing arrays in # zsh. # #### ## # Define a variable as an empty array # # The variable should already exist in the scope you want to use it in # # @param name ## ARRAY_define() { local name="${1}" eval "${name}=()" } ## # Get the current amount of entries inside an existing array # # @param name ## ARRAY_count() { local name="${1}" if [ -z "$(eval "echo \"\${${name}}\"")" ]; then echo "0" else eval "echo \"\${#${name}[@]}\"" fi } ## # Get a certain index stored inside an array # # The index is zero based. The first entry entry is therefore supposed to be 0. # If the used shell does only provide 1-based arrays this needs to be mapped # inside of this function accordingly # # @param name # @param index ## ARRAY_get() { local name="${1}" local index="$((${2}+1))" eval "echo \"\${${name}[${index}]}\"" } ## # Set a certain value stored to a certain index inside an array # # The index is zero based. The first entry entry is therefore supposed to be 0. # If the used shell does only provide 1-based arrays this needs to be mapped # inside of this function accordingly # # @param name # @param index # @param value ## ARRAY_set() { local name="${1}" local index="$((${2}+1))" local value="${3}" eval "${name}[${index}]=\"${value}\"" } ## # Push a given value to the end of the provided array name # # @param name # @param value ## ARRAY_push() { local name="${1}" local value="${2}" local index="$(($(eval "echo \${#${name}[@]}")+1))" eval "${name}[${index}]=\"${value}\"" } ## # Peek at a value from the end of the provided array name without removing it # # @param name ## ARRAY_peek() { local name="${1}" eval "echo \"\${${name}[\${#${name}[@]}]}\"" } ## # Pop a value from the end of the provided array name # # @param name ## ARRAY_pop() { local name="${1}" local index="$(eval "echo \${#${name}[@]}")" echo "$(ARRAY_peek "${name}")" ARRAY_unset "${name}" "$((${index}-1))" } ## # Unset a certain index from the given array # # @param name ## ARRAY_unset() { local name="${1}" local index="$((${2}+1))" eval "${name}[${index}]=()" } ================================================ FILE: cli/imports/colorizer.sh ================================================ #### # Copyright (c) 2012, Jakob Westhoff # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # - Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # - Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #### source "${COLORIZE_SH_SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE:-${0}}" )" && pwd )}/Compatibility/compatibility.sh" # Escape codes COLORIZER_START=${COLORIZER_START:="\033["} COLORIZER_END=${COLORIZER_END:="m"} # Default colors COLORIZER_blue=${COLORIZER_blue:="0;34"} COLORIZER_green=${COLORIZER_green:="0;32"} COLORIZER_cyan=${COLORIZER_cyan:="0;36"} COLORIZER_red=${COLORIZER_red:="0;31"} COLORIZER_purple=${COLORIZER_purple:="0;35"} COLORIZER_yellow=${COLORIZER_yellow:="0;33"} COLORIZER_gray=${COLORIZER_gray:="1;30"} COLORIZER_light_blue=${COLORIZER_light_blue:="1;34"} COLORIZER_light_green=${COLORIZER_light_green:="1;32"} COLORIZER_light_cyan=${COLORIZER_light_cyan:="1;36"} COLORIZER_light_red=${COLORIZER_light_red:="1;31"} COLORIZER_light_purple=${COLORIZER_light_purple:="1;35"} COLORIZER_light_yellow=${COLORIZER_light_yellow:="1;33"} COLORIZER_light_gray=${COLORIZER_light_gray:="0;37"} # Somewhat special colors COLORIZER_black=${COLORIZER_black:="0;30"} COLORIZER_white=${COLORIZER_white:="1;37"} COLORIZER_none=${COLORIZER_none:="0"} ## # Parse the input and return the ansi code output processed output ## COLORIZER_process_input() { local prompt_option="${1}" local strip_option="${2}" shift 2 local processed="${*}" local pseudoTag="" local stack ARRAY_define "stack" local result="" local ansiToken="" result="${processed%%<*}" if [ "${result}" != "" ] && [ "${result}" != "${processed}" ]; then # Cut outer content, which has been processed already processed="<${processed#*<}" fi while [ "${processed#*<}" != "${processed}" ]; do # Isolate first tag in stream pseudoTag="${processed#*<}" pseudoTag="${pseudoTag%%>*}" # Push/Pop tag to/from stack if [ "${pseudoTag:0:1}" != "/" ]; then ARRAY_push "stack" "${pseudoTag}" else if [ "${pseudoTag:1}" != "$(ARRAY_peek "stack")" ]; then echo "Mismatching colorize tag nesting at <$(ARRAY_peek "stack")>...<${pseudoTag}>" exit 42 fi ARRAY_pop "stack" >/dev/null fi # Apply ansi formatting if [ -z "${strip_option}" ]; then pseudoTag="${pseudoTag/-/_}" if [ "${pseudoTag:0:1}" != "/" ]; then # Opening Tag eval "ansiToken=\"\${COLORIZER_${pseudoTag}}\"" else # Closing Tag if [ "$(ARRAY_count "stack")" -eq 0 ]; then ansiToken="${COLORIZER_none}" else eval "ansiToken=\"\${COLORIZER_$(ARRAY_peek "stack")}\"" fi fi # Add escape codes ansiToken="${COLORIZER_START}${ansiToken}${COLORIZER_END}" if [ "${prompt_option}" = "SET" ]; then ansiToken="\[${ansiToken}\]" fi result="${result}${ansiToken}" fi # Cut processed portion from stream processed="${processed#*>}" # Update result with next content part result="${result}${processed%%<*}" done if [ "$(ARRAY_count "stack")" -ne 0 ]; then echo "Could not find closing tag for <$(ARRAY_peek "stack")>" exit 42 fi result="${result//</<}" result="${result//>/>}" echo "${result}" } ## # Parse a given colorize string and output the correctly escaped ansi-code # formatted string for it. # # This function is the only public API method to this utillity # # echo -e is used for output. # # The -n option may be specified, which will behave exactly like echo -n, aka # omitting the newline. # # To use ansi in a prompt without behaving badly, using the -p option. # # @option -n omit the newline # @option -p escape ansi for prompt usage # @option -s instead of replacing with ansi, just strip the tags # @param [string,...] ## colorize() { local OPTIND=1 local newline_option="" local prompt_option="" local strip_option="" local option="" while getopts ":nps" option; do case "${option}" in n) newline_option="SET";; p) prompt_option="SET";; s) strip_option="SET";; \?) echo "Invalid option (-${OPTARG}) given to colorize"; exit 42;; esac done shift $((OPTIND-1)) local processed_message="$(COLORIZER_process_input "${prompt_option}" "${strip_option}" "${@}")" if [ "${newline_option}" = "SET" ]; then echo -en "${processed_message}" else echo -e "${processed_message}" fi } # Allow alternate spelling alias colourise=colorize ================================================ FILE: cli/imports/common.sh ================================================ #!/bin/bash # colors red=$'\e[1;31m' grn=$'\e[1;32m' yel=$'\e[1;33m' blu=$'\e[1;34m' mag=$'\e[1;35m' cyn=$'\e[1;36m' end=$'\e[0m' # upload to transer.sh # use: transer "$file" transfer() { if [ $# -eq 0 ]; then echo -e "No arguments specified. Usage:\necho transfer /tmp/test.md\ncat /tmp/test.md | transfer test.md"; return 1; fi tmpfile=$( mktemp -t transferXXX ); if tty -s; then basefile=$(basename "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g'); curl --progress-bar --upload-file "$1" "https://transfer.sh/$basefile" >> $tmpfile; else curl --progress-bar --upload-file "-" "https://transfer.sh/$1" >> $tmpfile ; fi; echo "Your file: "; cat $tmpfile; file=$(cat $tmpfile); cat > $outputDir/last.txt <<< $file rm -f $tmpfile; } ================================================ FILE: cli/lastupload/last.txt ================================================ https://transfer.sh/FrW09/sync.tar.gz ================================================ FILE: cli/upload.sh ================================================ #!/bin/bash clear # ------------------------------ # # UPLOAD GEKKO HISTORY DATA # To transfer.sh + get link # # ------------------------------- # imports source imports/common.sh source imports/colorizer.sh # check config.sh if [ ! -f config.sh ]; then colorize "ERROR config.sh could not be found, copy config.sample.sh and modify to suit your needs!\n" return fi # import user config source config.sh # create output dir outputDir="lastupload" mkdir -p $outputDir # dir historyDir="$gekkoDir/history" echo colorize "COMPRESSING HISTORY DIRECTORY \n---\nDestination folder: $outputDir\n" colorize "Please wait, it might take a while...\n" # compress tar -czf "$outputDir/sync.tar.gz" $historyDir # msg colorize "Compression completed.\n" colorize "UPLOADING TO TRANSFER.SH \n---\n" # upload transfer "$outputDir/sync.tar.gz" colorize "\n\nCompleted.\n" colorize "Saved lastfile src to: $outputDir/last.txt\n" # remove old compressed file rm -rf "$outputDir/sync.tar.gz" ================================================ FILE: strategies/RSI_BULL_BEAR.js ================================================ /* RSI Bull and Bear Use different RSI-strategies depending on a longer trend 3 feb 2017 (CC-BY-SA 4.0) Tommie Hansen https://creativecommons.org/licenses/by-sa/4.0/ */ // req's var log = require ('../core/log.js'); var config = require ('../core/util.js').getConfig(); // strategy var strat = { /* INIT */ init: function() { this.name = 'RSI Bull and Bear'; this.requiredHistory = config.tradingAdvisor.historySize; this.resetTrend(); // debug? set to flase to disable all logging/messages (improves performance) this.debug = false; // performance config.backtest.batchSize = 1000; // increase performance config.silent = true; config.debug = false; // add indicators this.addIndicator('maSlow', 'SMA', this.settings.SMA_long ); this.addIndicator('maFast', 'SMA', this.settings.SMA_short ); this.addIndicator('BULL_RSI', 'RSI', { interval: this.settings.BULL_RSI }); this.addIndicator('BEAR_RSI', 'RSI', { interval: this.settings.BEAR_RSI }); // debug stuff this.startTime = new Date(); this.stat = { bear: { min: 100, max: 0 }, bull: { min: 100, max: 0 } }; }, // init() /* RESET TREND */ resetTrend: function() { var trend = { duration: 0, direction: 'none', longPos: false, }; this.trend = trend; }, /* get lowest/highest for backtest-period */ lowHigh: function( rsi, type ) { let cur; if( type == 'bear' ) { cur = this.stat.bear; if( rsi < cur.min ) this.stat.bear.min = rsi; // set new if( rsi > cur.max ) this.stat.bear.max = rsi; } else { cur = this.stat.bull; if( rsi < cur.min ) this.stat.bull.min = rsi; // set new if( rsi > cur.max ) this.stat.bull.max = rsi; } }, /* CHECK */ check: function() { // get all indicators let ind = this.indicators, maSlow = ind.maSlow.result, maFast = ind.maFast.result, rsi; // BEAR TREND if( maFast < maSlow ) { rsi = ind.BEAR_RSI.result; if( rsi > this.settings.BEAR_RSI_high ) this.short(); else if( rsi < this.settings.BEAR_RSI_low ) this.long(); if(this.debug) this.lowHigh( rsi, 'bear' ); //log.debug('BEAR-trend'); } // BULL TREND else { rsi = ind.BULL_RSI.result; if( rsi > this.settings.BULL_RSI_high ) this.short(); else if( rsi < this.settings.BULL_RSI_low ) this.long(); if(this.debug) this.lowHigh( rsi, 'bull' ); //log.debug('BULL-trend'); } }, // check() /* LONG */ long: function() { if( this.trend.direction !== 'up' ) // new trend? (only act on new trends) { this.resetTrend(); this.trend.direction = 'up'; this.advice('long'); //log.debug('go long'); } if(this.debug) { this.trend.duration++; log.debug ('Long since', this.trend.duration, 'candle(s)'); } }, /* SHORT */ short: function() { // new trend? (else do things) if( this.trend.direction !== 'down' ) { this.resetTrend(); this.trend.direction = 'down'; this.advice('short'); } if(this.debug) { this.trend.duration++; log.debug ('Short since', this.trend.duration, 'candle(s)'); } }, /* END backtest */ end: function(){ let seconds = ((new Date()- this.startTime)/1000), minutes = seconds/60, str; minutes < 1 ? str = seconds + ' seconds' : str = minutes + ' minutes'; log.debug('===================================='); log.debug('Finished in ' + str); log.debug('===================================='); if(this.debug) { let stat = this.stat; log.debug('RSI low/high for period'); log.debug('BEAR low/high: ' + stat.bear.min + ' / ' + stat.bear.max); log.debug('BULL low/high: ' + stat.bull.min + ' / ' + stat.bull.max); } } }; module.exports = strat; ================================================ FILE: strategies/RSI_BULL_BEAR.toml ================================================ # SMA Trends SMA_long = 1000 SMA_short = 50 # BULL BULL_RSI = 10 BULL_RSI_high = 80 BULL_RSI_low = 60 # BEAR BEAR_RSI = 15 BEAR_RSI_high = 50 BEAR_RSI_low = 20 # BULL/BEAR is defined by the longer SMA trends # if SHORT over LONG = BULL # if SHORT under LONG = BEAR ================================================ FILE: strategies/RSI_BULL_BEAR_ADX.js ================================================ /* RSI Bull and Bear + ADX modifier 1. Use different RSI-strategies depending on a longer trend 2. But modify this slighly if shorter BULL/BEAR is detected - (CC-BY-SA 4.0) Tommie Hansen https://creativecommons.org/licenses/by-sa/4.0/ - NOTE: Requires custom indicators found here: https://github.com/Gab0/Gekko-extra-indicators (c) Gabriel Araujo Howto: Download + add to gekko/strategies/indicators */ // req's var log = require('../core/log.js'); var config = require('../core/util.js').getConfig(); // strategy var strat = { /* INIT */ init: function() { // core this.name = 'RSI Bull and Bear + ADX'; this.requiredHistory = config.tradingAdvisor.historySize; this.resetTrend(); // debug? set to false to disable all logging/messages/stats (improves performance in backtests) this.debug = false; // performance config.backtest.batchSize = 1000; // increase performance config.silent = true; // NOTE: You may want to set this to 'false' @ live config.debug = false; // SMA this.addIndicator('maSlow', 'SMA', this.settings.SMA.long ); this.addIndicator('maFast', 'SMA', this.settings.SMA.short ); // RSI this.addIndicator('BULL_RSI', 'RSI', { interval: this.settings.BULL.rsi }); this.addIndicator('BEAR_RSI', 'RSI', { interval: this.settings.BEAR.rsi }); // ADX this.addIndicator('ADX', 'ADX', this.settings.ADX.adx ); // MOD (RSI modifiers) this.BULL_MOD_high = this.settings.BULL.mod_high; this.BULL_MOD_low = this.settings.BULL.mod_low; this.BEAR_MOD_high = this.settings.BEAR.mod_high; this.BEAR_MOD_low = this.settings.BEAR.mod_low; // debug stuff this.startTime = new Date(); // add min/max if debug if( this.debug ){ this.stat = { adx: { min: 1000, max: 0 }, bear: { min: 1000, max: 0 }, bull: { min: 1000, max: 0 } }; } /* MESSAGES */ // message the user about required history log.info("===================================="); log.info('Running', this.name); log.info('===================================='); log.info("Make sure your warmup period matches SMA_long and that Gekko downloads data if needed"); // warn users if( this.requiredHistory < this.settings.SMA.long ) { log.warn("*** WARNING *** Your Warmup period is lower then SMA_long. If Gekko does not download data automatically when running LIVE the strategy will default to BEAR-mode until it has enough data."); } }, // init() /* RESET TREND */ resetTrend: function() { var trend = { duration: 0, direction: 'none', longPos: false, }; this.trend = trend; }, /* get low/high for backtest-period */ lowHigh: function( val, type ) { let cur; if( type == 'bear' ) { cur = this.stat.bear; if( val < cur.min ) this.stat.bear.min = val; // set new else if( val > cur.max ) this.stat.bear.max = val; } else if( type == 'bull' ) { cur = this.stat.bull; if( val < cur.min ) this.stat.bull.min = val; // set new else if( val > cur.max ) this.stat.bull.max = val; } else { cur = this.stat.adx; if( val < cur.min ) this.stat.adx.min = val; // set new else if( val > cur.max ) this.stat.adx.max = val; } }, /* CHECK */ check: function() { // get all indicators let ind = this.indicators, maSlow = ind.maSlow.result, maFast = ind.maFast.result, rsi, adx = ind.ADX.result; // BEAR TREND // NOTE: maFast will always be under maSlow if maSlow can't be calculated if( maFast < maSlow ) { rsi = ind.BEAR_RSI.result; let rsi_hi = this.settings.BEAR.high, rsi_low = this.settings.BEAR.low; // ADX trend strength? if( adx > this.settings.ADX.high ) rsi_hi = rsi_hi + this.BEAR_MOD_high; else if( adx < this.settings.ADX.low ) rsi_low = rsi_low + this.BEAR_MOD_low; if( rsi > rsi_hi ) this.short(); else if( rsi < rsi_low ) this.long(); if(this.debug) this.lowHigh( rsi, 'bear' ); } // BULL TREND else { rsi = ind.BULL_RSI.result; let rsi_hi = this.settings.BULL.high, rsi_low = this.settings.BULL.low; // ADX trend strength? if( adx > this.settings.ADX.high ) rsi_hi = rsi_hi + this.BULL_MOD_high; else if( adx < this.settings.ADX.low ) rsi_low = rsi_low + this.BULL_MOD_low; if( rsi > rsi_hi ) this.short(); else if( rsi < rsi_low ) this.long(); if(this.debug) this.lowHigh( rsi, 'bull' ); } // add adx low/high if debug if( this.debug ) this.lowHigh( adx, 'adx'); }, // check() /* LONG */ long: function() { if( this.trend.direction !== 'up' ) // new trend? (only act on new trends) { this.resetTrend(); this.trend.direction = 'up'; this.advice('long'); if( this.debug ) log.info('Going long'); } if( this.debug ) { this.trend.duration++; log.info('Long since', this.trend.duration, 'candle(s)'); } }, /* SHORT */ short: function() { // new trend? (else do things) if( this.trend.direction !== 'down' ) { this.resetTrend(); this.trend.direction = 'down'; this.advice('short'); if( this.debug ) log.info('Going short'); } if( this.debug ) { this.trend.duration++; log.info('Short since', this.trend.duration, 'candle(s)'); } }, /* END backtest */ end: function() { let seconds = ((new Date()- this.startTime)/1000), minutes = seconds/60, str; minutes < 1 ? str = seconds.toFixed(2) + ' seconds' : str = minutes.toFixed(2) + ' minutes'; log.info('===================================='); log.info('Finished in ' + str); log.info('===================================='); // print stats and messages if debug if(this.debug) { let stat = this.stat; log.info('BEAR RSI low/high: ' + stat.bear.min + ' / ' + stat.bear.max); log.info('BULL RSI low/high: ' + stat.bull.min + ' / ' + stat.bull.max); log.info('ADX min/max: ' + stat.adx.min + ' / ' + stat.adx.max); } } }; module.exports = strat; ================================================ FILE: strategies/RSI_BULL_BEAR_ADX.toml ================================================ [SMA] long = 1000 short = 50 [BULL] rsi = 10 high = 80 low = 60 mod_high = 5 mod_low = -5 [BEAR] rsi = 15 high = 50 low = 20 mod_high = 15 mod_low = -5 [ADX] adx = 3 high = 70 low = 50 ================================================ FILE: strategies/TEMA.js ================================================ /* TEMA Triple EMA strategy with 'safety net' --- Uses 1x TEMA to go long/short if short trend is over TEMA. On top of this it uses a longer SMA as a safety net and simple stays out of the market if short SMA is under that SMA. --- The general idea is to buy in good market conditions and simply not be a part of longer downwards trends. */ // req's var log = require ('../core/log.js'); var config = require ('../core/util.js').getConfig(); // strategy var strat = { /* INIT */ init: function() { // base this.name = 'TEMA'; this.requiredHistory = config.tradingAdvisor.historySize; this.debug = false; // outputs messages, set to false to increase performance // add indicators and reset trend this.resetTrend(); this.addTulipIndicator('maSlow', 'tema', { optInTimePeriod: this.settings.long }); this.addTulipIndicator('maFast', 'sma', { optInTimePeriod: this.settings.short }); // check if long SMA is to be used if( this.settings.SMA_long > 0 ) { this.useSafety = true; this.addTulipIndicator('maSlowest', 'sma', { optInTimePeriod: this.settings.SMA_long }); } // set startTime to measure execution time @ end() this.startTime = new Date(); }, // init() /* RESET TREND */ resetTrend: function() { var trend = { duration: 0, direction: 'none', longPos: false, }; this.trend = trend; }, // resetTrend() /* CHECK */ check: function() { // do nothing if we don't got enough history if( this.candle.close.length < this.requiredHistory ) return; // fetch indicators let ti = this.tulipIndicators; let maFast = ti.maFast.result.result, maSlow = ti.maSlow.result.result; // check if safety option > 0 if( this.useSafety ) { let maSlowest = ti.maSlowest.result.result; if( maSlow < maSlowest ) { this.short(); return; // quit } } // other rules if( maFast > maSlow ) { this.long(); } else if( maFast < maSlow ) { this.short(); } }, // check() /* LONG */ long: function() { if( this.trend.direction !== 'up' ) { this.resetTrend(); this.trend.direction = 'up'; this.advice('long'); } if( this.debug ) { this.trend.duration++; log.debug ('Positive since', this.trend.duration, 'candle(s)'); } }, /* SHORT */ short: function() { if( this.trend.direction !== 'down' ) { this.resetTrend(); this.trend.direction = 'down'; this.advice('short'); } if( this.debug ) { this.trend.duration++; log.debug ('Negative since', this.trend.duration, 'candle(s)'); } }, /* END */ end: function() { let seconds = ((new Date()- this.startTime)/1000), minutes = seconds/60, str; minutes < 1 ? str = seconds + ' seconds' : str = minutes + ' minutes'; log.debug('Finished in ' + str); } }; // strat{} /* EXPORT */ module.exports = strat; ================================================ FILE: strategies/TEMA.toml ================================================ # Short / Long (EMA/TEMA) short = 10 long = 80 # Safety (SMA, 0 = disable) SMA_long = 200 ================================================ FILE: syncAll/config.sample.sh ================================================ #!/bin/bash # Gekko directory # Relative -or- absolute to where you have gekko tools installed gDir='../../gekko' ================================================ FILE: syncAll/download.sh ================================================ #!/bin/bash clear ### Download sync files @ ./sync/last.txt and replace files in Gekko with these new files ### # colors grn=$'\e[1;32m' yel=$'\e[1;33m' mag=$'\e[1;35m' cyn=$'\e[1;36m' end=$'\e[0m' # check config.sh if [ ! -f config.sh ]; then printf "${red}ERROR${end} config.sh could not be found, copy config.sample.sh and modify to suit your needs!\n" return fi # import user config ($gDir) source config.sh outputDir="sync" # get latest file from github git pull file=$(cat $outputDir/last.txt) saveFile='sync.tar.gz'; # get $filename function get() { if [ $# -eq 0 ]; then echo -e "No arguments specified."; return 1; fi echo echo curl "$1" >> $saveFile; } # get the file printf "Downloading file ${yel}$file${end}, please stand by..."; get $file printf "\n\n" # untar printf "Unpacking ${yel}$saveFile${end}...\n\n" tar -xvzf $saveFile echo # sync new > old (and replace) printf "Replacing old with new @ ${yel}gekko/ > $gDir ${end}\n\n" rsync -ah gekko/* $gDir echo # remove crap rm -rf gekko rm -rf sync.tar.gz printf "${grn}Completed.${end}\n\n" ================================================ FILE: syncAll/sync/last.txt ================================================ https://transfer.sh/AKPh1/sync.tar.gz ================================================ FILE: syncAll/upload.sh ================================================ #!/bin/bash clear # colors red=$'\e[1;31m' grn=$'\e[1;32m' yel=$'\e[1;33m' blu=$'\e[1;34m' mag=$'\e[1;35m' cyn=$'\e[1;36m' end=$'\e[0m' # check config.sh if [ ! -f config.sh ]; then printf "${red}ERROR${end} config.sh could not be found, copy config.sample.sh and modify to suit your needs!\n" return fi # import user config ($gDir) source config.sh outputDir="sync" mkdir -p $outputDir # dir string DIRS="$gDir/strategies $gDir/config" # ask user if history should be included or not read -p "${yel}Include history?${end} [y/n]: " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]] then DIRS+=" $gDir/history" echo "${cyn}OK -- including history${end}" fi echo printf "Compressing the files/folders ${yel}$DIRS${end} \nDestination folder: ${yel}$outputDir${end}\n" printf "${grn}Please wait...${end}\n\n" # compress tar -czf "$outputDir/sync.tar.gz" $DIRS echo printf "${yel}Compression completed.${end}\n\n" # upload to transer.sh transfer() { if [ $# -eq 0 ]; then echo -e "No arguments specified. Usage:\necho transfer /tmp/test.md\ncat /tmp/test.md | transfer test.md"; return 1; fi tmpfile=$( mktemp -t transferXXX ); if tty -s; then basefile=$(basename "$1" | sed -e 's/[^a-zA-Z0-9._-]/-/g'); curl --progress-bar --upload-file "$1" "https://transfer.sh/$basefile" >> $tmpfile; else curl --progress-bar --upload-file "-" "https://transfer.sh/$1" >> $tmpfile ; fi; echo "Your file: "; cat $tmpfile; file=$(cat $tmpfile); cat > $outputDir/last.txt <<< $file rm -f $tmpfile; } printf "${grn}Uploading to transfer.sh, please wait...${end}\n\n" transfer "$outputDir/sync.tar.gz" printf "\n" printf "${yel}Done.${end}\n\n" printf "Saved lastfile src to: ${yel}$outputDir/last.txt${end}\n\n" # remove old compressed file rm -rf "$outputDir/sync.tar.gz" ================================================ FILE: temp/system/functions.php ================================================ ]*?(\/?)>/i",'<$1$2>', $str); return $str; } # prp:
 + print_r
	function prp($str, $color = ''){ echo '
'; print_r($str); echo '
'; } function prph($str){ echo '
=======================================
'; echo '
'; print_r($str); echo '
'; echo '
=======================================
'; } # get all files in a dir function listFiles( $dir ){ $files = @array_diff(scandir($dir), array('.', '..', '.gitignore')); if( !$files ) $files = 'Error: No files reside within the directory ' . $dir; return $files; } # contains # sample: if( contains('something', $source) ){ /* string 'something' existed in $source */ } function contains($needle, $haystack) { return strpos($haystack, $needle) !== false; } # rtrim + ltrim function rmspace($str){ $data = rtrim(ltrim($str, ' '), ' '); $data = str_replace(" ", '', $data); return $data; } function numfix($str){ $data = str_replace(',','.',$str); $data = htmlentities($data); $data = rmspace($data); return $data; } # date diff function date_between($a, $b){ $a = new DateTime($a); $b = new DateTime($b); return $b->diff($a); } # T-date split e.g. 2017-24-12T16:00:00.000Z > 2017-24-12 16:00:00 function tdate($str){ $arr = explode('T', $str); $date = $arr[0]; $time = explode('.', $arr[1])[0]; return $date .' ' .$time; } # convert ms to days, hours etc function secondsToHuman($str){ $a = new \DateTime('@0'); $b = new \DateTime("@$str"); $diff = $a->diff($b); if( $diff->days > 0 ){ return $diff->format('%ad, %hh'); } else { return $diff->format('%hh'); } } # curl get function curl_get($url) { defined(SERVER_TIMEOUT) ? $timeout = SERVER_TIMEOUT : $timeout = 600; $curl = curl_init($url); curl_setopt($curl, CURLOPT_ENCODING, 0); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120); curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); $result = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); if ( $status != 200 ) { die("Error: call to URL $url failed with status $status, response $result, curl_error " . curl_error($curl) . ", curl_errno " . curl_errno($curl)); } curl_close($curl); return $result; } # measure time (simple) function timer_start(){ $a = microtime(true); return $a; } function timer_end($start){ $end = microtime(true); $diff = ($end-$start); // secondsls $diff = round($diff*100)/100; // conver to minutes if( $diff > 65 ) { $diff = round(($diff/60)*10)/10 . 'min'; } else { $diff = $diff . 's'; } // or just use seconds return $diff; } # output table from query; requires PDO::FETCHASSOC from query result function sqlTable($res, $class = 'tbl', $echo = true, $id = false ){ $html = ''; $head = $res[0]; if($id) $id = " id='$id'"; $html .= ""; foreach($head as $k=>$v){ $html .= ""; } $html .= ""; foreach( $res as $key => $val ){ $html .= ""; foreach($head as $i=>$h){ $html .= ""; } $html .= ""; } $html .= "
$k
" . $val[$i] . "
"; if($echo) { echo $html; } else { return $html; } } # flatten arrays function array_flatten( $a, $key=NULL) { $r = array(); if(is_array($a))foreach($a as $k=>$v)$r=array_merge($r,array_flatten($v,$k)); else $r[$key]=$a; return $r; } /*----------------------------------------------------- SIMPLIFIED CURL GET CACHE FUNC example curl_cache('http://google.com', 'cache/mycachefile.php', '1 hour'); -----------------------------------------------------*/ function curl_cache($src, $file, $time){ $exists = file_exists($file); $time = "+" . $time; $isExternal = false; if (strpos($src, 'http') !== false) { $isExternal = true; } // file does not exist or is over x time if( !$exists || ( $exists && time() > strtotime("$time", filemtime($file))) ) { if( $isExternal ){ defined(SERVER_TIMEOUT) ? $timeout = SERVER_TIMEOUT : $timeout = 600; $curl = curl_init($src); curl_setopt($curl, CURLOPT_ENCODING, 1); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120); curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept-Encoding: gzip,deflate')); // important -- reduce doc by 90% $data = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); if( $status === 200 ){ file_put_contents( $file, gzencode($data) ); } curl_close($curl); } // $isExternal // not external, is a string of some sort -- so just put it in a file else { file_put_contents( $file, gzencode($src) ); } } // file exists, just get it else { $data = gzdecode( file_get_contents($file) ); } // return return $data; } // curl_cache() /*----------------------------------------------------- CURL POST uri object with vars {} -----------------------------------------------------*/ function curl_post($url, $vars) { defined(SERVER_TIMEOUT) ? $timeout = SERVER_TIMEOUT : $timeout = 600; $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE); curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json",'Accept-Encoding: gzip,deflate')); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_POSTFIELDS, $vars); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120); curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); $data = curl_exec($curl); $status = curl_getinfo($curl, CURLINFO_HTTP_CODE); $arr['data'] = $data; $arr['status'] = $status; $arr = (object) $arr; curl_close($curl); return $arr; } // used to posting to 'self' function curl_post2($url, $vars) { defined(SERVER_TIMEOUT) ? $timeout = SERVER_TIMEOUT : $timeout = 600; $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $vars); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 120); curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); $data = curl_exec($curl); curl_close($curl); return $data; } function curl_post_cache( $url, $vars, $file, $cacheTime ) { $exists = file_exists($file); $time = "+" . $cacheTime; // file does not exist or is over x time if( !$exists || ( $exists && time() > strtotime("$time", filemtime($file))) ) { $data = curl_post($url, $vars); # only cache file if everything was ok if( $data->status === 200 ){ file_put_contents( $file, gzencode(json_encode($data)) ); } } // file exists, just get it else { $data = json_decode(gzdecode(file_get_contents($file))); } $data->data = json_decode($data->data); return $data; } ?> ================================================ FILE: temp/system/user.config.sample.php ================================================ # TEST

some test

readable date function timeToDate( $str, $format = 'Y-m-d' ) { return date($format, $str); } /* min/max date range for a pair - get min/max date range and convert to readable date requires db-handle and table name - return array with date_min/date_max */ function minMax( $db, $table ) { $sql = " SELECT strftime('%Y-%m-%d %H:%M', datetime(MIN(start), 'unixepoch')) as date_min, strftime('%Y-%m-%d %H:%M', datetime(MAX(start), 'unixepoch')) as date_max FROM `$table` "; $q = $db->query($sql); $q = $q->fetchAll()[0]; // always just one return $q; } /* CRITICAL CHECKS */ // check if user config exists if( !file_exists('system/user.config.php') ) die('ERROR Could not find user.config.php, make sure you have createad it.'); require_once 'system/functions.php'; require_once 'system/user.config.php'; // check if the path is correct if( !file_exists($gekko_path . 'README.md') ) die('ERROR The path to your Gekko install is wrong or not working.'); /* SETUP PATHS */ $gp = $gekko_path; $paths = [ 'gekko' => $gp, 'history' => $gp . 'history/', ]; $paths = json_decode(json_encode($paths)); #prp($paths); /* GET ALL HISTORY FILES */ $files = listFiles( $paths->history ); // ..then remove any not ending with '.db' foreach($files as $key => $value) { $cur = end(explode('.', $files[$key])); // explode + get last if( $cur !== 'db' ) unset($files[$key]); } $files = array_values($files); // re-index echo 'history files'; prp($files); /* TRY SQLite STUFF */ // init $db, TEMP: use first db $first = $paths->history . $files[0]; $db = new PDO('sqlite:' . $first) or die('ERROR Could not connect to database.'); $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); $sql = " SELECT name FROM main.sqlite_master WHERE type = 'table' "; $tables = $db->query($sql); $tables = $tables->fetchAll(); // filter out tables not containg candles_ foreach( $tables as $key => $val ) { $cur = $tables[$key]; $name = $val['name']; if( !contains('candles_', $name) || contains('sqlite', $name) ) unset($tables[$key]); } echo 'tables'; prp($tables); // get min/max echo 'min/max'; $stuff = minMax($db, $tables[0]['name']); prp($stuff); $db = null; ?>
================================================ FILE: wsl-install/gekko_install.sh ================================================ #!/bin/bash clear echo "-------------------------------------------" echo 'INSTALLING GEKKO + DEPENDECIES' echo '-------------------------------------------' echo 'This will take a while, go get some coffe' sleep 3 sudo su apt-get update -y && apt-upgrade -y && apt-get update -y curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - apt-get install nodejs -y apt-get install build-essential -y apt-get install git -y cd /mnt/c/ mkdir www cd www git clone git://github.com/askmike/gekko.git cd gekko npm install --only=production cd exchange npm install --only=production cd .. npm install tulind apt-get install nano -y apt-get autoremove -y node gekko --ui ================================================ FILE: wsl-install/readme.md ================================================ # Install Gekko in Windows bash ##### Prerequisites (required) * Install Bash on Windows 10: https://docs.microsoft.com/en-us/windows/wsl/install-win10 * C-drive in Windows (or change all references to c to any other drive you might have) #### How-to ##### Simple way 1. Open bash 2. curl -sL https://raw.githubusercontent.com/tommiehansen/gekko_tools/master/wsl-install/gekko_install.sh | sudo bash - ##### Manual way 1. open bash (win-key + type 'bash' + ENTER) 2. sudo su 3. apt-get update -y && apt-upgrade -y && apt-get update -y Above will take some time, expect it to take 10-20 minutes. 4. curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - 5. apt-get install nodejs -y 6. apt-get install build-essential -y 7. apt-get install git -y 8. apt-get install jed && apt-get install nano 9. cd /mnt/c/ 10. mkdir www 11. cd www 12. git clone git://github.com/askmike/gekko.git 13. cd gekko 14. npm install --only=production cd exchange npm install --only=production cd .. 15. npm install tulind 16. apt-get autoremove -y 17. node gekko --ui