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 "<light-red>ERROR</light-red> 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 "<light-red>ERROR</light-red> 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 <light-yellow>$file</light-yellow>, please stand by...."
get $file
printf "\n\n"
# untar
colorize "Unpacking <light-yellow>$saveFile</light-yellow>...\n"
tar -xvzf $saveFile
echo
# sync new > old (and replace)
colorize "Replacing old with new @ <light-yellow>$gekkoDir/history</light-yellow>\n"
rsync -ah gekko/* $gekkoDir
echo
# remove crap
rm -rf gekko
rm -rf "$outputDir/sync.tar.gz"
colorize "<light-green>Completed.</light-green>\n"
================================================
FILE: cli/imports/Compatibility/bash/array.bash
================================================
####
# Copyright (c) 2012, Jakob Westhoff <jakob@qafoo.com>
#
# 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 <jakob@qafoo.com>
#
# 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 <f.sowade@r9e.de>
#
# 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 <jakob@qafoo.com>
#
# 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 <jakob@qafoo.com>
#
# 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 "<light-red>ERROR</light-red> 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: <light-yellow>$outputDir</light-yellow>\n"
colorize "<light-green>Please wait, it might take a while...</light-green>\n"
# compress
tar -czf "$outputDir/sync.tar.gz" $historyDir
# msg
colorize "<light-yellow>Compression completed.</light-yellow>\n"
colorize "UPLOADING TO TRANSFER.SH \n---\n"
# upload
transfer "$outputDir/sync.tar.gz"
colorize "\n\n<light-yellow>Completed.</light-yellow>\n"
colorize "Saved lastfile src to: <light-yellow>$outputDir/last.txt</light-yellow>\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
================================================
<?php
/*
this file needs cleaning and classes
*/
# GET FILTER
function _G($var){
$val = false;
if( isset($_GET[$var]) ) { $val = $_GET[$var]; }
$val = htmlspecialchars($val);
$val = strip_tags($val); // remove tags
return $val;
}
# POST filter
function _P($var){
$val = false;
if( isset($_POST[$var]) ) { $val = $_POST[$var]; }
#$val = htmlspecialchars($val);
$val = strip_tags($val); // remove tags
return $val;
}
# FILTER DATA, remove all tags
function filterData($str){
$str = preg_replace("/<([a-z][a-z0-9]*)[^>]*?(\/?)>/i",'<$1$2>', $str);
return $str;
}
# prp: <pre> + print_r
function prp($str, $color = ''){ echo '<pre style="color: '. $color .'">'; print_r($str); echo '</pre>'; }
function prph($str){
echo '<pre>=======================================</pre>';
echo '<pre>'; print_r($str); echo '</pre>';
echo '<pre>=======================================</pre>';
}
# 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 .= "<table class='$class'$id><thead><tr>";
foreach($head as $k=>$v){
$html .= "<th>$k</th>";
}
$html .= "</tr></thead><tbody>";
foreach( $res as $key => $val ){
$html .= "<tr>";
foreach($head as $i=>$h){
$html .= "<td>" . $val[$i] . "</td>";
}
$html .= "</tr>";
}
$html .= "</tbody></table>";
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
================================================
<?php
/*
*** GEKKO LOCAL PATH ***
Must point to your install
-
If you get errors, just try until it works or really
check that the path is correct.
*/
$gekko_path = '../../../www/gekko/';
================================================
FILE: temp/test.php
================================================
<!doctype html>
<html>
<head>
<title># TEST</title>
<style>
html {font-size: 62.5%; }
body{padding:2% 0;font-family:monospace,mono-space;font-size:1.5rem;color:deeppink;text-align:center;overlow-x:hidden}*,:after,:before{box-sizing:border-box}body,html{height:100%}
body { background-image: linear-gradient(to top,#060311,#140b3c); background-attachment: fixed; }
h1{color:#ff1493;font-weight:400;font-size:1.2rem;margin:20px 0 30px}
pre,textarea{display:block;text-align:left;border:1px dashed #ff0;color:#ff0;padding:20px;vertical-align:top;transition:all .5s ease;cursor:default;min-width:30%;max-width:100%;position:relative;border-radius:2px;line-height:1.4}
pre { margin-bottom: 20px; }
pre:after,textarea:after{content:'$';line-height:1;position:absolute;left:20px;top:-7px;background:#140b3c;padding:0 5px}
pre b,textarea b{font-size:40px;font-weight:400}
body,html { height: 100%; margin: 0; }
body { margin-bottom: 200px; }
h1,h2 { color: deeppink; font-weight: normal; }
h1 { font-size: 1.8rem; }
section { max-width: 600px; position: relative; margin:0 auto; }
/* pre stuff */
pre { margin-bottom: 30px; }
pre:nth-child(2n+1){ border-color: deeppink; color: deeppink; }
pre:nth-child(3n+1){ border-color: cyan; color: cyan; }
pre:focus,pre:hover{color:#fff;border-color:lime; }
</style>
</head>
<body>
<section>
<h1>some test</h1>
<?php
// JS-date > 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('<b>ERROR</b> 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('<b>ERROR</b> 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('<b>ERROR</b> 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;
?>
</section>
</body>
</html>
================================================
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
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
SYMBOL INDEX (23 symbols across 2 files)
FILE: temp/system/functions.php
function _G (line 8) | function _G($var){
function _P (line 18) | function _P($var){
function filterData (line 28) | function filterData($str){
function prp (line 34) | function prp($str, $color = ''){ echo '<pre style="color: '. $color .'">...
function prph (line 35) | function prph($str){
function listFiles (line 43) | function listFiles( $dir ){
function contains (line 52) | function contains($needle, $haystack) {
function rmspace (line 58) | function rmspace($str){
function numfix (line 64) | function numfix($str){
function date_between (line 73) | function date_between($a, $b){
function tdate (line 80) | function tdate($str){
function secondsToHuman (line 89) | function secondsToHuman($str){
function curl_get (line 104) | function curl_get($url)
function timer_start (line 132) | function timer_start(){ $a = microtime(true); return $a; }
function timer_end (line 133) | function timer_end($start){
function sqlTable (line 147) | function sqlTable($res, $class = 'tbl', $echo = true, $id = false ){
function array_flatten (line 174) | function array_flatten( $a, $key=NULL)
function curl_cache (line 192) | function curl_cache($src, $file, $time){
function curl_post (line 256) | function curl_post($url, $vars)
function curl_post2 (line 284) | function curl_post2($url, $vars)
function curl_post_cache (line 303) | function curl_post_cache( $url, $vars, $file, $cacheTime )
FILE: temp/test.php
function timeToDate (line 35) | function timeToDate( $str, $format = 'Y-m-d' ) {
function minMax (line 47) | function minMax( $db, $table )
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (59K chars).
[
{
"path": ".gitignore",
"chars": 76,
"preview": "gitpush.sh\r\n*.tar\r\n*.gz\r\ncli/config.sh\r\nsyncAll/config.sh\r\nuser.config.php\r\n"
},
{
"path": "cli/config.sample.sh",
"chars": 126,
"preview": "#!/bin/bash\r\n\r\n# Gekko directory\r\n# Relative -or- absolute to where you have gekko tools installed\r\n\r\ngekkoDir='../../ge"
},
{
"path": "cli/download.sh",
"chars": 1387,
"preview": "#!/bin/bash\nclear\n\n# ------------------------------\n#\n# Download sync files @ lastupload/last.txt\n# ...and replace files"
},
{
"path": "cli/imports/Compatibility/bash/array.bash",
"chars": 3521,
"preview": "####\n# Copyright (c) 2012, Jakob Westhoff <jakob@qafoo.com>\n# \n# All rights reserved.\n# \n# Redistribution and use in sou"
},
{
"path": "cli/imports/Compatibility/compatibility.sh",
"chars": 1803,
"preview": "####\n# Copyright (c) 2012, Jakob Westhoff <jakob@qafoo.com>\n# \n# All rights reserved.\n# \n# Redistribution and use in sou"
},
{
"path": "cli/imports/Compatibility/default/array.sh",
"chars": 2648,
"preview": "####\n# Copyright (c) 2013, Florian Sowade <f.sowade@r9e.de>\n#\n# All rights reserved.\n#\n# Redistribution and use in sourc"
},
{
"path": "cli/imports/Compatibility/zsh/array.zsh",
"chars": 3628,
"preview": "####\n# Copyright (c) 2012, Jakob Westhoff <jakob@qafoo.com>\n# \n# All rights reserved.\n# \n# Redistribution and use in sou"
},
{
"path": "cli/imports/colorizer.sh",
"chars": 6030,
"preview": "####\n# Copyright (c) 2012, Jakob Westhoff <jakob@qafoo.com>\n# \n# All rights reserved.\n# \n# Redistribution and use in sou"
},
{
"path": "cli/imports/common.sh",
"chars": 743,
"preview": "#!/bin/bash\n\n# colors\nred=$'\\e[1;31m'\ngrn=$'\\e[1;32m'\nyel=$'\\e[1;33m'\nblu=$'\\e[1;34m'\nmag=$'\\e[1;35m'\ncyn=$'\\e[1;36m'\nen"
},
{
"path": "cli/lastupload/last.txt",
"chars": 38,
"preview": "https://transfer.sh/FrW09/sync.tar.gz\n"
},
{
"path": "cli/upload.sh",
"chars": 1160,
"preview": "#!/bin/bash\nclear\n\n# ------------------------------\n#\n# UPLOAD GEKKO HISTORY DATA\n# To transfer.sh + get link\n#\n# ------"
},
{
"path": "strategies/RSI_BULL_BEAR.js",
"chars": 3902,
"preview": "/*\r\n\tRSI Bull and Bear\r\n\tUse different RSI-strategies depending on a longer trend\r\n\t3 feb 2017\r\n\t\r\n\t(CC-BY-SA 4.0) Tommi"
},
{
"path": "strategies/RSI_BULL_BEAR.toml",
"chars": 283,
"preview": "# SMA Trends\r\nSMA_long = 1000\r\nSMA_short = 50\r\n\r\n# BULL\r\nBULL_RSI = 10\r\nBULL_RSI_high = 80\r\nBULL_RSI_low = 60\r\n\r\n# BEAR\r"
},
{
"path": "strategies/RSI_BULL_BEAR_ADX.js",
"chars": 6183,
"preview": "/*\r\n\tRSI Bull and Bear + ADX modifier\r\n\t1. Use different RSI-strategies depending on a longer trend\r\n\t2. But modify this"
},
{
"path": "strategies/RSI_BULL_BEAR_ADX.toml",
"chars": 188,
"preview": "[SMA]\nlong = 1000\nshort = 50\n\n[BULL]\nrsi = 10\nhigh = 80\nlow = 60\nmod_high = 5\nmod_low = -5\n\n[BEAR]\nrsi = 15\nhigh = 50\nlo"
},
{
"path": "strategies/TEMA.js",
"chars": 3033,
"preview": "/*\r\n\tTEMA\r\n\tTriple EMA strategy with 'safety net'\r\n\t---\r\n\tUses 1x TEMA to go long/short if short trend is over TEMA.\r\n\tO"
},
{
"path": "strategies/TEMA.toml",
"chars": 95,
"preview": "# Short / Long (EMA/TEMA)\r\nshort = 10\r\nlong = 80\r\n\r\n# Safety (SMA, 0 = disable)\r\nSMA_long = 200"
},
{
"path": "syncAll/config.sample.sh",
"chars": 116,
"preview": "#!/bin/bash\n\n# Gekko directory\n# Relative -or- absolute to where you have gekko tools installed\n\ngDir='../../gekko'\n"
},
{
"path": "syncAll/download.sh",
"chars": 1090,
"preview": "#!/bin/bash\nclear\n\n### Download sync files @ ./sync/last.txt and replace files in Gekko with these new files ###\n\n# colo"
},
{
"path": "syncAll/sync/last.txt",
"chars": 38,
"preview": "https://transfer.sh/AKPh1/sync.tar.gz\n"
},
{
"path": "syncAll/upload.sh",
"chars": 1803,
"preview": "#!/bin/bash\nclear\n\n# colors\nred=$'\\e[1;31m'\ngrn=$'\\e[1;32m'\nyel=$'\\e[1;33m'\nblu=$'\\e[1;34m'\nmag=$'\\e[1;35m'\ncyn=$'\\e[1;3"
},
{
"path": "temp/system/functions.php",
"chars": 8291,
"preview": "<?php\r\n\r\n\t/*\r\n\t\tthis file needs cleaning and classes\r\n\t*/\r\n\r\n\t# GET FILTER\r\n\tfunction _G($var){\r\n\t\t$val = false;\r\n\t\tif( "
},
{
"path": "temp/system/user.config.sample.php",
"chars": 203,
"preview": "<?php\n\n\t/*\n\t\t*** GEKKO LOCAL PATH ***\n\t\tMust point to your install\n\t\t-\n\t\tIf you get errors, just try until it works or r"
},
{
"path": "temp/test.php",
"chars": 3769,
"preview": "<!doctype html>\n<html>\n<head>\n\t<title># TEST</title>\n\t<style>\n\thtml {font-size: 62.5%; }\n\tbody{padding:2% 0;font-family:"
},
{
"path": "wsl-install/gekko_install.sh",
"chars": 668,
"preview": "#!/bin/bash\nclear\necho \"-------------------------------------------\"\necho 'INSTALLING GEKKO + DEPENDECIES'\necho '-------"
},
{
"path": "wsl-install/readme.md",
"chars": 1059,
"preview": "# Install Gekko in Windows bash\n\n##### Prerequisites (required)\n\n* Install Bash on Windows 10:\nhttps://docs.microsoft.co"
}
]
About this extraction
This page contains the full source code of the tommiehansen/gekko_tools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (50.7 KB), approximately 15.4k tokens, and a symbol index with 23 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.