Full Code of Gab0/japonicus for AI

master af4aaf74f8b2 cached
104 files
179.0 KB
48.0k tokens
216 symbols
1 requests
Download .txt
Showing preview only (202K chars total). Download the full file or copy to clipboard to get everything.
Repository: Gab0/japonicus
Branch: master
Commit: af4aaf74f8b2
Files: 104
Total size: 179.0 KB

Directory structure:
gitextract_koczj845/

├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yaml
├── evaluation/
│   ├── __init__.py
│   ├── benchmark/
│   │   ├── __init__.py
│   │   ├── benchmark.py
│   │   └── generateConfig.py
│   └── gekko/
│       ├── API.py
│       ├── __init__.py
│       ├── backtest.py
│       ├── dataset.py
│       ├── datasetOperations.py
│       └── statistics.py
├── exchangerun.csv
├── gekko_evolution.yml
├── japonicus/
│   ├── Settings.py
│   ├── __init__.py
│   ├── configIndicators.py
│   ├── configStrategies.py
│   ├── evolution_generations.py
│   ├── halt.py
│   ├── interface.py
│   ├── japonicus.py
│   └── options.py
├── japonicus-run
├── jlivetrader.py
├── livetrader/
│   ├── exchangeMonitor.py
│   ├── gekkoChecker.py
│   ├── gekkoTrigger.py
│   ├── japonicusResultSelector.py
│   └── strategyRanker.py
├── promoterz/
│   ├── README.md
│   ├── TOMLutils.py
│   ├── __init__.py
│   ├── environment.py
│   ├── evaluationBreak.py
│   ├── evaluationPool.py
│   ├── evolutionHooks.py
│   ├── evolutionToolbox.py
│   ├── functions.py
│   ├── locale.py
│   ├── logAnalysis.py
│   ├── logger.py
│   ├── metaPromoterz.py
│   ├── parameterOperations.py
│   ├── representation/
│   │   ├── Creator.py
│   │   ├── chromosome.py
│   │   ├── deapCreator.py
│   │   └── oldschool.py
│   ├── sequence/
│   │   ├── __init__.py
│   │   ├── locale/
│   │   │   └── standard_loop.py
│   │   └── world/
│   │       └── parallel_world.py
│   ├── statistics.py
│   ├── supplement/
│   │   ├── PRoFIGA.py
│   │   ├── age.py
│   │   └── phenotypicDivergence.py
│   ├── validation.py
│   ├── webServer/
│   │   ├── __init__.py
│   │   ├── core.py
│   │   ├── external_css_list.txt
│   │   ├── graphs.py
│   │   ├── layout.py
│   │   └── promoterz_style.css
│   └── world.py
├── requirements.txt
├── settings/
│   ├── _Global.toml
│   ├── _backtest.toml
│   ├── _bayesian.toml
│   ├── _binance.toml
│   ├── _dataset.toml
│   ├── _evalbreak.toml
│   └── _generation.toml
├── stratego/
│   ├── README.md
│   ├── __init__.py
│   ├── gekko_strategy.py
│   ├── indicator_properties.py
│   └── skeleton/
│       ├── dumbsum.js
│       └── ontrend.js
├── strategy_parameters/
│   ├── BBRSI.toml
│   ├── DUAL_RSI_BULL_BEAR.toml
│   ├── HL_TS.toml
│   ├── NEO.toml
│   ├── NEObigjap.toml
│   ├── PPO.toml
│   ├── RBB_ADX2_BB.toml
│   ├── RSI_BULL_BEAR.toml
│   ├── RSI_BULL_BEAR_ADX.toml
│   ├── RSI_BULL_BEAR_x2.toml
│   ├── WRSI_BULL_BEAR.toml
│   ├── foxhole.toml
│   ├── griewangk.toml
│   ├── quartic.toml
│   ├── rastrigin.toml
│   ├── rosenbrock.toml
│   ├── scalperNEO.toml
│   ├── scalperRBBA.toml
│   └── schwefel.toml
├── utilities/
│   ├── importer.sh
│   ├── poloUSDTBTC.js
│   ├── poloUSDTETH.js
│   └── poloUSDTLTC.js
└── version.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/Global/Windows.gitignore

# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk


### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/Global/Linux.gitignore

*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*


### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/Global/macOS.gitignore

*.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk


### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/Global/Emacs.gitignore

# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*

# Org-mode
.org-id-locations
*_archive

# flymake-mode
*_flymake.*

# eshell files
/eshell/history
/eshell/lastdir

# elpa packages
/elpa/

# reftex files
*.rel

# AUCTeX auto folder
/auto/

# cask packages
.cask/
dist/

# Flycheck
flycheck_*.el

# server auth directory
/server/

# projectiles files
.projectile

# directory configuration
.dir-locals.el


### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/Global/Vim.gitignore

# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags


### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/Global/Tags.gitignore

# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
TAGS
.TAGS
!TAGS/
tags
.tags
!tags/
gtags.files
GTAGS
GRTAGS
GPATH
GSYMS
cscope.files
cscope.out
cscope.in.out
cscope.po.out



### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/python.gitignore

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# dotenv
.env

# virtualenv
.venv/
venv/
ENV/

# Spyder project settings
.spyderproject

# Rope project settings
.ropeproject






### gekkoJaponicus
output
src


================================================
FILE: Dockerfile
================================================
FROM python:3.6.6-jessie


ENV LANG en_US.UTF-8

# install dependencies;
#RUN apt-get update -y
#RUN apt-get install software-properties-common python-software-properties -y


RUN apt-get update -y
RUN apt-get upgrade -y


RUN apt-get install python3-pip python3-numpy -y

RUN pip3.6 install --upgrade pip

COPY ./requirements.txt /opt/japonicus/requirements.txt

# those are required to build other python modules, so install first;
RUN pip3.6 install numpy cython pandas

RUN pip3.6 install --ignore-installed -r /opt/japonicus/requirements.txt


WORKDIR /opt/japonicus/

COPY . /opt/japonicus

EXPOSE 5000

RUN python3.6 --version

ENTRYPOINT ["python3.6", "/opt/japonicus/japonicus-run"]
CMD ["python3.6", "/opt/japonicus/japonicus-run", "--help"]


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2014-2017 Mike van Rossum mike@mvr.me

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
### What is japonicus and what it does
This is an implementation of genetic algorithm & bayesian evolution to develop strategies for digital coin trading bot <a href="https://github.com/askmike/gekko">Gekko</a>.

So you make a good strat, or get one from the internetz. Make sure its good, because this is not about miracles.

If you get good profit on strat standard settings or some random settings you made up, japonicus can find some setting set that improves the strategy, on some specific market/currency or overall.

Discord Group: `https://discord.gg/kYKHXnV`

## Instructions
Japonicus works on `python>=3.6`!
Check wiki for instructions on setup, workflow, methods, etc.

## Disclaimer

No matter how many years your training candles span or how convoluted or simple is your strategy,
your strategies/parameters that were profitable on backtest runs probably won't translate well to live trading.<br>
Altough japonicus is a fairly competent GA and will find a capable set of parameters in a few epoches,
we're yet to discover why the live trading runs seem an environment completely unrelated to backtest env, where
strategies/parameters that seemed good offline turn into live daily losses or below market gains.

You can send me a few coins to help me develop some ideas for binance trading bots,
as this kind of research involves a steady negative profit so I cannot sustain it indefinitely...
If something starts working I will share here or in our discord group. Those are my binance wallets:

```
LTC	LVhThMzJMC6aKBcA1KX4q3yk2ryBjfPGfH
ETH	0xceaa9bb655ed80ba36b55532fdd6e11e6e5b681b
```

## User Feedback

You all users of japonicus should report notable runs under an issue.
If some strat seems to be viable, send feedback so users can have a better point of entry for their own runs.<br>

## Future

Genetic Algorithms are a good way to fetch a good set of settings to run a strategy on gekko. <br>
But the real gamechanger is the strategy itself.<br>
The ideal evolution method would be a Genetic Programming that modifies strategy logic. <br>
This somewhat corresponds to `--skeleton` mode of japonicus, which lets the GA select indicators on a base strategy.


# Changelog

The changelog is important for the user as following modifications can cause bugs on related areas. Please report 'em ;)

```
v0.92
- Moving all gekko related functions to evaluation.gekko module. The purpose is making japonicus a general purpose
GA framework.


v0.91

- the evolution candle date ranges are now defined by given area in the map, instead of attached at each locale.


v0.90 

- web interface reworked - now it is the recommended method to run the ga's.
- locale creation/destruction chances updated.
- bayesian evolution method deprecated.

v0.80 

- supports gekko v0.6.X (only).
- Dockerfile and docker-compose methods revisited.
- automatic filter for multiple remote gekko urls (urls defined inside settings/global)
- live trading bot watcher at `jlivetrader.py`. For binance only, undocumented and experimental.


v0.70 

- log folder restructured
- configStrategies.py DEPRECATED; use only TOML parameters at the folder strategy_parameters.
    check TOML special syntax for parameter ranges at the wiki
- GA benchmark mode added
- Settings.py refactor
- Roundtrip exposure time filter


v0.58

- runs in Windows (not confirmed)
- Settings parameters can be passed on command line (check the --help)
- Multiple evolution datasets can be passed. `@Settings.py:dataset ->
  dataset_source is the first, add dataset_source1; dataset_source2 and so forth
for multiple datasets.`
- filter individues for minimum trade count (default: enabled@16 trades)
- backtest scores (profit and sharpe) to individue final score method is now a sum, not multiplication

v0.56 

- japonicus settings for strategies can be stored at strategy_parameters folder as .toml files
- automated refactor on entire codebase
- wiki is online, check it for instructions.
- various bugfixes
- log & results improvements
- daterange for locales now on locale logs (.csv)
- statistics methods remade.

v0.54

- Variation of Backtest result interpretation. check Settings.py -> genconf.interpreteBacktestProfit
- Focus on selecting best individues. Periodic evaluation on more candidates. Bugfixes on that department. 
- Result interface actually readable.
- Log better structured, with the summary at the top.
- Small clarifications on code.

v0.53

- Major aesthetics rework on code itself; now we can even have collaborators.
- Pretty run logs @ logs folder;
- Interchangeable backtest result interpretation (promoterz.evaluation.gekko:25)
- gekko API is now organized - backtest & dadataset functions separated.
- Genetic Algorithm settings controllable via command line. Check --help.
- Web interface more stable

v0.51
- Started tracking updates on changelog;

```


================================================
FILE: docker-compose.yaml
================================================
version: '3'
services:
  gekko:
    image: gekko
    volumes:
      - gekko-dir:/usr/src/app
    ports:
      - "3000:3000"
  japonicus:
    command: $JARGS
    
    image: japonicus
    build: .
    volumes:
      - gekko-dir:/root/gekko
    ports:
      - "5000:5000"

    depends_on:
      - gekko

volumes:
  gekko-dir:


================================================
FILE: evaluation/__init__.py
================================================
#!/bin/python
from .import gekko
from . import benchmark


================================================
FILE: evaluation/benchmark/__init__.py
================================================
#!/bin/python

from . import benchmark


================================================
FILE: evaluation/benchmark/benchmark.py
================================================
#!/bin/python

# source https://www.researchgate.net/publication/27382766_On_benchmarking_functions_for_genetic_algorithm
import random
import math


def evalRosenbrock(parameters):
    Result = pow(1-parameters[0], 2)
    Result += 100 * pow(pow(parameters[0], 2) - parameters[1], 2)

    return -Result


def evalGriewangk(parameters):
    Dimensions = 10
    Result = 1

    for w in range(Dimensions):
        W = w + 1
        Result += pow(parameters[w], 2) / 4000

    COSs = math.cos(parameters[0])
    for z in range(1, Dimensions):
        Z = z + 1
        COSs *= (math.cos(parameters[z]) / math.sqrt(Z))

    Result -= COSs

    return -Result


def evalRastrigin(parameters):
    Dimensions = 20
    Result = 10 * Dimensions

    for w in range(Dimensions):
        W = w + 1
        Result += pow(parameters[w], 2)
        Result -= 10 * (math.cos(2*math.pi*parameters[w]))

    return -Result


def evalSchwefel(parameters):
    A = 4189.829101
    Open = 10 * A
    Result = Open
    for w in range(10):
        W = w + 1
        Result += -parameters[w] * math.sin(math.sqrt(abs(parameters[w])))

    return -Result


def evalQuartic(parameters):
    Result = 0
    for w in range(30):
        W = w + 1
        Result += W * pow(parameters[w], 4) + random.gauss(0, 1)

    return -Result


def evalFoxHole(parameters):
    # MIN = 0.998003837794449325873406851315
    Result = 0.002
    a = [
        [-32, -16, 0, 16, 32,
         -32, -16, 0, 16, 32,
         -32, -16, 0, 16, 32,
         -32, -16, 0, 16, 32,
         -32, -16, 0, 16, 32],
        [-32, -32, -32, -32, -32,
         -16, -16, -16, -16, -16,
         0, 0, 0, 0, 0,
         16, 16, 16, 16, 16,
         32, 32, 32, 32, 32]
    ]

    for w in range(25):
        W = 1+w
        D = W
        for k in range(2):
            D += pow((parameters[k] - a[k][w]), 6)
        Result += (1/D)

    Result = 1/Result
    return -Result


def Evaluate(genconf, phenotype):
    evalFunctionName = list(phenotype.keys())[0]
    parameters = phenotype[evalFunctionName]
    parameters = [parameters[N] for N in sorted(list(parameters.keys()))]

    evalFunctions = {
        'quartic': evalQuartic,
        'foxhole': evalFoxHole,
        'schwefel': evalSchwefel,
        'rastrigin': evalRastrigin,
        'griewangk': evalGriewangk,
        'rosenbrock': evalRosenbrock
    }
    result = evalFunctions[evalFunctionName](parameters)

    return {
        'relativeProfit': result,
        'sharpe': 0,
        'trades': 25,
        'averageExposure': 0
    }


================================================
FILE: evaluation/benchmark/generateConfig.py
================================================
#!/bin/python
import pytoml

NBP = 30
PRANGE = [-1.28, 1.28]

NBP = 25
PRANGE = [-65536, 65536]

NBP = 10
PRANGE = [-500, 500]

NBP = 20
PRANGE = [-5.12, 5.12]

#NBP = 10
#PRANGE = [-600, 600]

#NBP = 2
#PRANGE = [-2.048, 2.048]

PARAMETERS = {}
for P in range(NBP):
    PNAME = 'P%i' % P
    PARAMETERS.update({PNAME: PRANGE})

TOMLTEXT = pytoml.dumps(PARAMETERS)
open('config.toml', 'w').write(TOMLTEXT)


================================================
FILE: evaluation/gekko/API.py
================================================
#!/bin/python
import os
import requests
import json
from subprocess import Popen, PIPE


def initializeGekko():  # not used yet.
    CMD = ['node', gekkoDIR + '/gekko', '--ui']
    D = Popen(CMD, stdin=PIPE, stdout=PIPE, stderr=PIPE)

    
def checkInstance(instanceUrl):
    try:
        Request = requests.get(instanceUrl)
    except Exception:
        return False
    if Request.text:
        return True


def httpPost(URL, data={}, Verbose=True):
    try:
        Request = requests.post(URL, json=data)
        Response = json.loads(Request.text)

    except ConnectionRefusedError:
        print("Error: Gekko comm error! Check your local Gekko instance.")
        exit()
    except Exception as e:
        if Verbose:
            print("Error: config failure")
            print(e)
            print(URL)
            print(data)
        return False

    return Response


def loadHostsFile(HostsFilePath):
    remoteGekkos = []
    if os.path.isfile(HostsFilePath):
        H = open(HostsFilePath).read().split('\n')
        for W in H:
            if W and not '=' in W and not '[' in W:
                remoteGekkos.append("http://%s:3000" % W)
    return remoteGekkos


================================================
FILE: evaluation/gekko/__init__.py
================================================
#!/bin/python
import os
import subprocess

from .import API
from .import dataset
from .import backtest
from .import datasetOperations
from .statistics import *
import pathlib

import promoterz


class GekkoEvaluator():
    def __init__(self):
        pass


SettingsFiles = [
    "generation",
    "Global",
    "dataset",
    #"indicator",
    "backtest",
    "evalbreak"
]


def showBacktestResult(backtestResult, dataset=None):
    messageBackbone = ''.join([
        'Test on random candles...  ',
        'relativeProfit: %.3f \t',
        'nbTrades: %.1f\t',
        'sharpe: %.2f'
    ])

    message = messageBackbone % (
        backtestResult['relativeProfit'],
        backtestResult['trades'],
        backtestResult['sharpe']
    )

    if dataset:
        message += "\n\t\t%s\t%s" % (dataset.textDaterange(),
                                     dataset.textSpecifications())

    return message


def parseDatasetInfo(purpose, candlestickDataset):
    textdaterange = datasetOperations.dateRangeToText(
        candlestickDataset.daterange)
    print()
    Text = "\n%s candlestick dataset %s\n" % (purpose, textdaterange)
    Text += candlestickDataset.textSpecifications() + '\n'
    return Text


def showPrimaryInfo(Logger, evolutionDatasets, evaluationDatasets):
    for evolutionDataset in evolutionDatasets:
        Logger.log(
            parseDatasetInfo("evolution", evolutionDataset),
            target="Header"
        )
    if evaluationDatasets:
        for evaluationDataset in evaluationDatasets:
            Logger.log(
                parseDatasetInfo("evaluation", evaluationDataset),
                target="Header"
            )



class GekkoEvaluationPool(promoterz.evaluationPool.EvaluationPool):
    #def __init__(self, World, Urls, poolsize, individual_info):
    #    pass

    def ejectURL(self, Index):
        self.Urls.pop(Index)
        self.lasttimes.pop(Index)
        self.lasttimesperind.pop(Index)
        self.poolsizes.pop(Index)

    def distributeIndividuals(self, tosimulation):
        nb_simulate = len(tosimulation)
        sumtimes = sum(self.lasttimes)
        # stdtime = sum(self.lasttimes)/len(self.lasttimes)
        std = nb_simulate / len(self.Urls)
        # stdTPI = sum(self.lasttimesperind)/len(self.lasttimesperind)
        #print(stdTPI)
        if sumtimes:
            vels = [1 / x for x in self.lasttimes]
            constant = nb_simulate / sum(vels)
            proportions = [max(1, x * constant) for x in vels]
        else:
            proportions = [std for x in self.Urls]
        proportions = [int(round(x)) for x in proportions]
        pC = lambda x: random.randrange(0, len(x))
        pB = lambda x: x.index(min(x))
        pM = lambda x: x.index(max(x))
        while sum(proportions) < nb_simulate:
            proportions[pB(proportions)] += 1
            print('+')
        while sum(proportions) > nb_simulate:
            proportions[pM(proportions)] -= 1
            print('-')
        print(proportions)
        assert (sum(proportions) == nb_simulate)
        distribution = []
        L = 0
        for P in proportions:
            distribution.append(tosimulation[L: L + P])
            L = L + P
        return distribution


EvaluationPool = GekkoEvaluationPool


def ResultToIndividue(result, individue):
    individue.fitness.values = (result['relativeProfit'], result['sharpe'])
    individue.trades = result['trades']
    individue.averageExposure = result['averageExposure'] / 3600000


def showIndividue(evaldata):
    return "~ bP: %.3f\tS: %.3f\tnbT:%.3f" % (
        evaldata['relativeProfit'], evaldata['sharpe'], evaldata['trades']
    )


def validateSettings(settings):
    # LOCATE & VALIDATE RUNNING GEKKO INSTANCES FROM CONFIG URLs;
    possibleInstances = settings['Global']['GekkoURLs']
    validatedInstances = []
    for instance in possibleInstances:
        Response = API.checkInstance(instance)
        if Response:
            validatedInstances.append(instance)
            print("found gekko @ %s" % instance)
        else:
            print("unable to locate %s" % instance)

    if validatedInstances:
        settings['Global']['GekkoURLs'] = validatedInstances

    else:
        print("Aborted: No running gekko instances found.")
        return False

    GekkoPath = settings['Global']['gekkoPath'] + '/gekko.js'
    GekkoPath = GekkoPath.replace("$HOME", str(pathlib.Path.home()))
    # FIX THIS;
    if False and not os.path.isfile(GekkoPath):
        print(
            "Aborted: gekko.js not found" + 
            "on path specified @Settings.py;\n%s" % GekkoPath)
        return False

    return True


# DEPRECATED;
def launchGekkoChildProcess(settings):
    gekko_args = [
        'node',
        '--max-old-space-size=8192',
        settings['global']['gekkoPath'] + '/web/server.js',
    ]
    gekko_server = subprocess.Popen(gekko_args,
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE)
    return gekko_server




================================================
FILE: evaluation/gekko/backtest.py
================================================
#!/bin/python
from .API import httpPost


def interpreteBacktestProfitv1(backtest):
    return backtest['relativeProfit']


def interpreteBacktestProfitv2(backtest):
    return backtest['relativeProfit'] - backtest['market']


def interpreteBacktestProfitv3(backtest):
    if backtest['relativeProfit'] < 0 and backtest['market'] < 0:
        return backtest['relativeProfit']

    else:
        return backtest['relativeProfit'] - backtest['market']


def getInterpreterBacktestInfo(v):
    info = {
        'v1': "<shown profit> = <backtest profit>",
        'v2': "<shown profit> = <backtest profit> - <market profit>",
        'v3': "\nif <backtest profit> > 0: <shown profit> = <backtest profit> - <market profit> \nelse <shown profit> = <backtest profit> "
}

    return "interpreter %s: " % v + info[v]


def runBacktest(
    GekkoInstanceUrl,
    TradeSetting,
    Dataset,
    candleSize=10,
    gekko_config=None,
    Debug=False,
):
    gekko_config = createConfig(
        TradeSetting, Dataset.specifications, Dataset.daterange, candleSize,
        gekko_config, Debug
    )
    url = GekkoInstanceUrl + '/api/backtest'
    fakeReport = {
        'relativeProfit': 0, 'market': 0, 'trades': 0,
        'sharpe': 0, 'roundtrips': []
    }
    try:
        result = httpPost(url, gekko_config)
        # sometime report is False(not dict)
        if type(result['performanceReport']) is bool:
            print("Warning: performanceReport not found, probable Gekko fail!")
            print(Dataset.specifications)
            # That fail is so rare that has no impact.. still happens randomly;
            return fakeReport  # fake backtest report
    except Exception as e:
        print(e)
        return fakeReport

    # rProfit = result['report']['relativeProfit']
    # nbTransactions = result['report']['trades']
    # market = result['report']['market']
    backtestResult = result['performanceReport']
    if 'roundtrips' in result.keys():
        backtestResult['roundtrips'] = result['roundtrips']

    return backtestResult


def Evaluate(backtestconf, Datasets, phenotype, GekkoInstanceUrl):
    # IndividualToSettings(IND, STRAT) is a function that depends on GA algorithm,
    # so should be provided;
    result = [
        runBacktest(
            GekkoInstanceUrl,
            phenotype,
            Dataset,
            candleSize=backtestconf.candleSize,
            Debug=backtestconf.gekkoDebug,
        )
        for Dataset in Datasets
    ]
    interpreter = {
        'v1': interpreteBacktestProfitv1,
        'v2': interpreteBacktestProfitv2,
        'v3': interpreteBacktestProfitv3,
    }
    # --INTERPRETE BACKTEST RESULT;
    RelativeProfits = [interpreter[backtestconf.interpreteBacktestProfit](R) for R in result]
    avgTrades = sum([R['trades'] for R in result]) / len(Datasets)
    mRelativeProfit = sum(RelativeProfits) / len(RelativeProfits)
    avgSharpe = sum([R['sharpe'] for R in result if R['sharpe']])
    avgSharpe = avgSharpe / len(Datasets)

    # --CALCULATE EXPOSURE DURATIONS;
    for R in result:
        R['totalExposure'] = 0
        R['averageExposure'] = 0
        if 'roundtrips' in R.keys():
            for roundtrip in R['roundtrips']:
                R['totalExposure'] += roundtrip['duration']
            R['averageExposure'] = R['totalExposure'] / len(R['roundtrips']) if len(R['roundtrips']) else 0

    avgExposure = sum(R['averageExposure'] for R in result) / len(Datasets)
    return {
        'relativeProfit': mRelativeProfit,
        'sharpe': avgSharpe,
        'trades': avgTrades,
        'averageExposure': avgExposure
    }


def createConfig(
        TradeSetting, Database, DateRange,
        candleSize=10, gekko_config=None, Debug=False
):
    TradeMethod = list(TradeSetting.keys())[0]
    CONFIG = {
        "watch": Database,
        "paperTrader": {
            "fee": 0.25,  # declare deprecated 'fee' so keeps working w/ old gekko;
            "feeMaker": 0.15,
            "feeTaker": 0.25,
            "feeUsing": 'maker',
            "slippage": 0.05,
            "simulationBalance": {"asset": 1, "currency": 100},
            "reportRoundtrips": True,
            "enabled": True,
        },
        "tradingAdvisor": {
            "enabled": True,
            "method": TradeMethod,
            "candleSize": candleSize,  # candleSize: smaller = heavier computation + better possible results;
            "historySize": 10,
        },
        TradeMethod: TradeSetting[TradeMethod],
        "backtest": {"daterange": DateRange},
        "performanceAnalyzer": {"riskFreeReturn": 2, "enabled": True},
        "valid": True,
        "data": {
            "candleProps": [
                "id", "start", "open", "high", "low", "close", "vwp", "volume", "trades"
            ],
            "indicatorResults": True,
            "report": True,
            "roundtrips": True,
            "trades": True,
        },
        "backtestResultExporter": {
            "enabled": True,
            "writeToDisk": False,
            "data": {
                "stratUpdates": False,
                "roundtrips": True,
                "stratCandles": False,
                "stratCandleProps": [
                    "open"
                ],
                "trades": False
            }
        }
    }

    if gekko_config == None:
        gekko_config = CONFIG

    return gekko_config


================================================
FILE: evaluation/gekko/dataset.py
================================================
#!/bin/python
import random
import datetime
from .API import httpPost


def getAllScanset(GekkoURL):
    URL = GekkoURL + '/api/scansets'
    RESP = httpPost(URL)
    return RESP['datasets']


def selectCandlestickData(GekkoURL,
                          exchange_source=None,
                          avoidCurrency=None,
                          minDays=None):
    DataSetPack = getAllScanset(GekkoURL)
    specKeys = ['exchange', 'currency', 'asset']
    scanset = []

    # IF EXCHANGE SPECIFICATIONS ARE TO BRE IGNORED;
    if 'autoselect' in exchange_source.keys():
        if exchange_source['autoselect']:
            exchange_source = None

    # SEARCH CANDIDATE DATASETS AMONG THOSE OBTAINED FROM GEKKO API;
    for s in DataSetPack:
        Valid = True
        for k in specKeys:
            if exchange_source and s[k] != exchange_source[k]:
                Valid = False
        if avoidCurrency and not exchange_source:
            if s["asset"] == avoidCurrency:
                Valid = False
        if Valid:
            scanset.append(s)

    # IN CASE NO CANDLESTICK DATASET IS COMPATIBLE;
    if len(scanset) == 0:
        if exchange_source:
            raise RuntimeError(
                "scanset not available: %s\n\tscanset found: %s" %
                (exchange_source, DataSetPack)
            )

        else:
            raise RuntimeError("no scanset available! check Gekko candle database.")

    # SEARCH ON ALL FOUND SCANSETS;
    for EXCHANGE in scanset:
        ranges = EXCHANGE['ranges']
        # no ranges found?
        if not ranges:
            # print("No scansets found for %s" % EXCHANGE)
            continue
        range_spans = [x['to'] - x['from'] for x in ranges]
        LONGEST = range_spans.index(max(range_spans))
        EXCHANGE['max_span'] = range_spans[LONGEST]
        EXCHANGE['max_span_index'] = LONGEST

    # COMPILE MOST INTERESTING SCANSETS;
    availableScanset = [exchange for exchange in scanset
                        if 'max_span' in exchange.keys()]

    exchange_longest_spans = [x['max_span'] for x in availableScanset]

    if minDays is not None:
        exchange_longest_spans = [
            span for span in exchange_longest_spans
            if span > minDays * 24 * 3600
        ]

    # Without scansets we cannot continue.
    if not exchange_longest_spans:
        print("FATAL: No scanset available.")
        return None

    best_exchange = exchange_longest_spans.index(max(exchange_longest_spans))
    best_exchange_span =\
        availableScanset[best_exchange]['max_span_index']
    chosenScansetRange =\
        availableScanset[best_exchange]['ranges'][best_exchange_span]

    chosenScansetSpecifications = {
        K: availableScanset[best_exchange][K]
        for K in availableScanset[best_exchange]
        if K in specKeys
    }

    return chosenScansetSpecifications, chosenScansetRange


def getCandles(globalconf, DateRange, Dataset, size=100):
    base = random.choice(globalconf.GekkoURLs)
    URL = base + "/api/getCandles"
    CONFIG = {
        "watch": Dataset.specifications,
        "daterange": DateRange,
        "adapter": "sqlite",
        "sqlite": {
            "path": "plugins/sqlite",
            "dataDirectory": "history",
            "version": 0.1,
            "dependencies": [{"module": "sqlite3", "version": "3.1.4"}],
        },
        "candleSize": size,
    }
    RESULT = httpPost(URL, CONFIG)
    return RESULT


def getDateRange(Limits, deltaDays=3):
    DateFormat = "%Y-%m-%d %H:%M:%S"
    deltams = deltaDays * 24 * 60 * 60
    DateRange = {
        "from": "%s" % epochToString(Limits['to'] - deltams),
        "to": "%s" % epochToString(Limits['to']),
    }
    return DateRange


def getRandomDateRange(Limits, deltaDays):
    FLms = Limits['from']
    TLms = Limits['to']
    deltams = deltaDays * 24 * 60 * 60
    if deltams > (TLms - FLms):
        print(
            "Fatal: deltaDays on Settings.py set to a value bigger than current dataset.\n Edit Settings file to fit your chosen candlestick data."
        )
        exit(1)
    Start = random.randint(FLms, TLms - deltams) if deltaDays else FLms
    End = (Start + deltams) if deltaDays else TLms
    DateRange = {
        "from": "%s" % epochToString(Start),
        "to": "%s" % epochToString(End)
    }
    return DateRange


def epochToString(D):
    return datetime.datetime.utcfromtimestamp(D).strftime(
        "%Y-%m-%d %H:%M:%S"
    )


================================================
FILE: evaluation/gekko/datasetOperations.py
================================================
#!/bin/python
import evaluation
import random


class CandlestickDataset():
    def __init__(self, specifications, daterange):
        self.daterange = daterange
        self.specifications = specifications

    def restrain(self, deltaDays):
        if not deltaDays:
            return

        deltams = deltaDays * 24 * 60 * 60
        restrainedInit = self.daterange['to'] - deltams
        self.daterange['from'] = max(self.daterange['from'], restrainedInit)

    def textDaterange(self):
        return dateRangeToText(self.daterange)

    def textSpecifications(self):
        message = "%s/%s @%s" % (self.specifications["asset"],
                                 self.specifications["currency"],
                                 self.specifications["exchange"])

        return message

    def __str__(self):
        return self.textSpecification()


def getRandomSectorOfDataset(sourceDataset, deltaDays):

    G = evaluation.gekko.dataset.getRandomDateRange
    dateRange = G(sourceDataset.daterange, deltaDays)
    newDataset = CandlestickDataset(sourceDataset.specifications,
                                    dateRange)

    return newDataset


def getLocaleDataset(World, Type='evolution'):

    localeDataset = []
    for DS in range(World.conf.backtest.ParallelCandlestickDataset):
        sourceDataset = random.choice(World.EnvironmentParameters['evolution'])

        newDataset = getRandomSectorOfDataset(sourceDataset,
                                              World.conf.backtest.deltaDays)
        localeDataset.append(newDataset)

    return localeDataset


def dateRangeToText(dateRange):
    def convertDateRange(x):
        if type(x) == int:
            return evaluation.gekko.dataset.epochToString(x) 
        else:
            return x

    Range = [
        convertDateRange(dateRange[x]) for x in ['from', 'to']
    ]
    Text = "%s to %s" % (Range[0], Range[1])
    return Text


================================================
FILE: evaluation/gekko/statistics.py
================================================
#!/bin/python

from deap import tools
import numpy as np

epochStatisticsNames = {
    'avg': 'Average profit',
    'std': 'Profit variation',
    'min': 'Minimum profit',
    'max': 'Maximum profit',
    'size': 'Population size',
    'maxsize': 'Max population size',
    'avgTrades': 'Avg trade number',
    'sharpe': 'Avg sharpe ratio',
    'avgExposure': "Avg exposure time",
    'nbElderDies': 'Elder dies count'
}

periodicStatisticsNames = {
    'evaluationScore': "Evaluation Score",
    'evaluationScoreOnSecondary': "Score on Secondary Dataset"
}



def compileStats(locale):
    # --get proper evolution statistics;
    Stats = locale.stats.compile(locale.population)
    Stats['dateRange'] = ' '.join([DR.textDaterange()
                                   for DR in locale.Dataset])\
                                       if not locale.EPOCH else None
    Stats['maxsize'] = locale.POP_SIZE
    Stats['size'] = len(locale.population)
    Stats['avgTrades'] = locale.extraStats['avgTrades']
    Stats['avgExposure'] = locale.extraStats['avgExposure'] 
    #Stats['nbElderDies'] = locale.extraStats['nbElderDies']
    Stats['sharpe'] = np.mean([x.fitness.values[1] for x in locale.population])
    Stats['evaluationScoreOnSecondary'] = locale.lastEvaluationOnSecondary
    Stats['evaluationScore'] = locale.lastEvaluation
    locale.lastEvaluationOnSecondary = None
    locale.lastEvaluation = None
    Stats['id'] = locale.EPOCH
    locale.EvolutionStatistics.append(Stats)
    locale.World.logger.write_evolution_logs(
        locale.EPOCH, locale.EvolutionStatistics, locale.name
    )


def showStatistics(locale):
    # show information;
    Stats = locale.EvolutionStatistics[locale.EPOCH]
    print("EPOCH %i\t&%i" % (locale.EPOCH, locale.extraStats['nb_evaluated']))
    statnames = ['max', 'avg', 'min',
                 'std', 'size', 'maxsize',
                 'avgTrades', 'sharpe', 'avgExposure',
                 # 'nbElderDies'
    ]
    statisticsText = []
    for s in range(len(statnames)):
        SNAME = statnames[s]
        SVAL = Stats[SNAME]
        currentStatisticsText = "%s" % epochStatisticsNames[SNAME]
        if not SVAL % 1:
            currentStatisticsText += " %i" % SVAL
        else:
            currentStatisticsText += " %.3f" % SVAL
        statisticsText.append(currentStatisticsText)

    columnWidth = max([len(STXT) for STXT in statisticsText]) + 3
    for j in range(0, len(statisticsText), 2):
        print(''.join(word.ljust(columnWidth) for word in statisticsText[j:j+2]))

    print()


================================================
FILE: exchangerun.csv
================================================
EXCHANGE,CURRENCY,ASSET,STRATEGY
binance,usdt,btc,RSI_BULL_BEAR_ADX
binance,usdt,bcc,RSI_BULL_BEAR_ADX
binance,usdt,ltc,RSI_BULL_BEAR_ADX
binance,usdt,neo,RSI_BULL_BEAR_ADX
binance,usdt,qtum,RSI_BULL_BEAR_ADX
binance,usdt,bnb,RSI_BULL_BEAR_ADX
binance,usdt,eth,RSI_BULL_BEAR_ADX


================================================
FILE: gekko_evolution.yml
================================================
- name: prepare machine software and install Gekko Trading Bot
  hosts: all
  remote_user: ec2-user 
  become_method: sudo
  tasks:

  - name: update cache
    become: yes
    command: "yum update -y"

  - name: Install environment components
    become: yes

    shell: yum install -y {{item}}
    with_items:
    - git
    - tmux

  - name: get NODEjs
    become: yes
    #shell: "curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -" UBUNTU LINUX;
    shell: "curl -sL https://rpm.nodesource.com/setup_8.x | bash -"

  - name: install NODEjs
    become: yes
    command: "yum install -y nodejs"

  - name: clone gekko git repo
    command: "git clone https://github.com/askmike/gekko"
    ignore_errors: yes
    
  - name: install gekko nodejs libs
    command: "npm install --only=production"
    args:
      chdir: "gekko"

  - name: install problematic nodejs lib
    become: yes
    command: "npm install -G sqlite3"

  - name: edit gekko UI config
    shell: sed -i 's/{{ item }}/0.0.0.0/' gekko/web/vue/UIconfig.js
    with_items:
    - 127.0.0.1

  - name: edit gekko UI config pt2
    command: "sed -i 's/localhost/{{ inventory_hostname }}/' gekko/web/vue/UIconfig.js"

  - copy:
      src: ~/gekko/history
      dest: ~/gekko

  - name: run gekko UI
    command: "tmux new -d -s Gekko 'node gekko.js --ui; detach \\;'"
    args:
      chdir: "gekko"


================================================
FILE: japonicus/Settings.py
================================================
#!/bin/python
import js2py
from pathlib import Path

from .configStrategies import cS
from .configIndicators import cI

import os
import pytoml


class makeSettings(dict):
    def __init__(self, entries):
        for K in entries.keys():
            if type(entries[K]) == dict:
                entries[K] = makeSettings(entries[K])
        self.__dict__.update(entries)
        self.update(entries)


def getSettings(SettingsFiles=[], specific=None):
    HOME = str(Path.home())

    settings = {}

    for SettingsFile in SettingsFiles:
        settings[SettingsFile] = loadTomlSettings(SettingsFile)

    return settings

    s = {
        # gekko global settings;
        'global': loadTomlSettings('global'),
        # gekko backtest settings;
        'backtest': loadTomlSettings('backtest'),
        # evaluation break settings;
        'evalbreak': loadTomlSettings('evalbreak'),
        # genetic algorithm settings;
        'generations': loadTomlSettings('generations'),

        'dataset': loadTomlSettings('dataset'),

        'strategies': cS,
        'indicators': cI,
        'skeletons': {
            'ontrend': {
                "SMA_long": 1000,
                "SMA_short": 50
            }
        }
    }

    if specific is not None:
        if not specific:
            return makeSettings(s)
        else:
            return makeSettings(s[specific])

    return s


def loadTomlSettings(settingsDivisionName):
    userSettingsAndDefaultSettings = [
        '%s.toml' % settingsDivisionName,
        '_%s.toml' % settingsDivisionName
    ]
    for targetFile in userSettingsAndDefaultSettings:
        filePath = os.path.join('settings', targetFile)
        if os.path.isfile(filePath):
            Settings = pytoml.load(open(filePath))
            return Settings

    exit("Failed to load settings! %s" % settingsDivisionName)


def get_configjs(filename="example-config.js"):
    with open(filename, "r") as f:
        text = f.read()
    text = text.replace("module.exports = config;","config;")
    return js2py.eval_js(text).to_dict()


================================================
FILE: japonicus/__init__.py
================================================
#!/bin/python

from .japonicus import *
from . import options
from . import interface


================================================
FILE: japonicus/configIndicators.py
================================================
#!/bin/python
cI = {
    "ADX": {"active": True, "period": 14, "thresholds.up": 70, "thresholds.down": 50},
    "ATR": {"active": True, "period": 14, "thresholds.up": 70, "thresholds.down": 50},
    "PPO": {
        "active": True,
        "short": (6, 18),  # short EMA
        "long": (13, 39),  # long EMA
        "signal": (1, 18),  # 100 * (shortEMA - longEMA / longEMA)
        "thresholds.down": (-0.5, 0.),  # trend thresholds
        "thresholds.up": (0., 0.5),  # trend thresholds
    },
    "TSI": {
        "active": True,
        "thresholds.up": (15, 35),
        "thresholds.down": (-35, -15),
        "short": (3, 12),
        "long": (15, 35),
    },
    "LRC": {
        "active": True,
        "thresholds.up": (15, 35),
        "thresholds.down": (-35, -15),
        "depth": (3, 18),
    },
    "RSI": {
        "active": True,
        "interval": (7, 21),  # weight
        "thresholds.down": (15, 45),  # trend thresholds
        "thresholds.up": (45, 140),  # trend thresholds
    },
    "SMMA": {
        "active": True,
        "weight": (7, 16),
        "thresholds.up": (0, 0.1),
        "thresholds.down": (-0.1, 0),
    },
    "DEMA": {
        "active": True,
        "short": (7, 15),
        "long": (12, 35),
        "thresholds.up": (0, 0.1),
        "thresholds.down": (-0.1, 0),
    },
    "CCI": {
        "active": True,
        "consistant": (7, 21),  # constant multiplier. 0.015 gets to around 70% fit
        "history": (45, 135),  # history size, make same or smaller than history
        "thresholds.down": (-150, -50),  # trend thresholds
        "thresholds.up": (50, 150),  # trend thresholds
        "thresholds.persistence": (4, 10),
    },
}


================================================
FILE: japonicus/configStrategies.py
================================================
#!/bin/python

NEG = lambda v: (-v[1], -v[0])
cS = {
    # Define values for strat settings for strategies to be used
    # on japonicus;
    # Each value can be a tuple of limits or just a base value.
    "ontrend" : {
    "bull_momentum_high": 80,
    "bull_momentum_low": 60,
    "bear_momentum_high": 50,
    "bear_momentuum_low": 20,
    "sec_high": 70,
    "sec_low": 50

        },
    "rsi_bbands": {

"NbDevUp": 2,
"NbDevDn": 2,
"TimePeriod": 9,
"rsi_high": 60,
"rsi_low": 20,
"min_hold": 5,
"swing_trade": 0.5
},
    
"RSI_BULL_BEAR" : {

# 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
},
    
"RSI_BULL_BEAR_ADXold" : {

# 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,

# ADX
"ADX": 3,
"ADX_high": 70,
"ADX_low": 50
},
    
"RSI_BULL_BEAR_ADX" : {

# 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,

# ADX
"ADX": 3,
"ADX_high": 70,
"ADX_low": 50,

"BULL_MOD_high": 5,
"BULL_MOD_low": -5,
"BEAR_MOD_high": 15,
"BEAR_MOD_low": -5
},
    
"Bestone" :{
    "customMACDSettings": {
        "optInFastPeriod": (3,10),
        "optInSlowPeriod": (20,50),
        "optInSignalPeriod": (5,15)
    },

    "customEMAshortSettings": {
        "optInTimePeriod": (5,15)
    },

    "customEMAlongSettings": {
        "optInTimePeriod": (15,26)
    },

    "customSTOCHSettings": {
        "optInFastKPeriod": (6, 14),
        "optInSlowKPeriod": (2,5),
        "optInSlowKMAType": (1,1),
        "optInSlowDPeriod": (2,5),
        "optInSlowDMAType": (1,1)
    },

    "customRSISettings": {
        "optInTimePeriod": (7,20)
    }

},

    
    "PPOTSI":{
        "PPO.short": (3,16),
        "PPO.long": (12,35),
        "PPO.signal":(3,21),
        "PPO.up": (0., 1),
        "PPO.down": (-1, 0.),
        "TSI.up": (10,40),
        "TSI.down": (-40,-10),
        "TSI.short": (3,18),
        "TSI.long": (10,42),
        "persistence": (1,10)
    },
    "Supertrend": {
        "atrEma":(1,10),
        "bandFactor": (1,10)
        },
    "PPOLRC":{
        "PPO.short": (3,12),
        "PPO.long": (15,35),
        "PPO.signal":(3,18),
        "PPO.up": (0., 0.5),
        "PPO.down": (-0.5, 0.),
        "LRC.up": (15,35),
        "LRC.down": (-35,-15),
        "LRC.depth": (3,18),
        "persistence": (1,5)
    },
    "buyatsellat": {
        'buyat': (1.03,1.20),
	'sellat': (0.92, 0.97), 
	'stop_loss_pct': (0.87, 0.95), 
	'sellat_up': (1.01,1.20)
    },
    "buyatsellatPPO": {
        'buyat': (1.03,1.20),
        'sellat': (0.92, 0.97), 
        'stop_loss_pct': (0.87, 0.95), 
        'sellat_up': (1.01,1.20),
        "short": (6,18), # short EMA
        "long": (13,39), # long EMA
        "signal": (1,18), # 100 * (shortEMA - longEMA / longEMA)
        "thresholds.down": (-0.5,0.), # trend thresholds
        "thresholds.up": (0.,0.5), # trend thresholds
        "thresholds.persistence": (2,10), # trend duration(count up by tick) thresholds
    },
    "DEMA":{
        "short": (1,10), # short EMA
        "long": (20,50), # long EMA
        "thresholds.down": (-0.5,0.1), # trend thresholds
        "thresholds.up": (-0.1,0.5), # trend thresholds
    },
    "MACD":{
        "short": (1,10), # short EMA
        "long": (20,50), # long EMA
        "signal": (9,18), # shortEMA - longEMA diff
        "thresholds.down": (-0.5,0.), # trend thresholds
        "thresholds.up": (0.,0.5), # trend thresholds
        "thresholds.persistence": (2,10), # trend duration(count up by tick) thresholds
    },
    "PPO":{
        "short": (6,18), # short EMA
        "long": (13,39), # long EMA
        "signal": (1,18), # 100 * (shortEMA - longEMA / longEMA)
        "thresholds.down": (-0.5,0.), # trend thresholds
        "thresholds.up": (0.,0.5), # trend thresholds
        "thresholds.persistence": (2,10), # trend duration(count up by tick) thresholds
    },
    # Uses one of the momentum indicators but adjusts the thresholds when PPO is bullish or bearish
    # Uses settings from the ppo and momentum indicator config block
    "varPPO":{ # TODO: merge PPO config
        "short": (6,18), # short EMA
        "long": (13,39), # long EMA
        "signal": (1,18), # 100 * (shortEMA - longEMA / longEMA)
        "thresholds.down": (-0.5,0.), # trend thresholds
        "thresholds.up": (0.,0.5), # trend thresholds
        "thresholds.persistence": (0,4), # trend duration(count up by tick) thresholds
        "momentum": (0, 2.99999), # index of ["RSI", "TSI", "UO"]
        # new threshold is default threshold + PPOhist * PPOweight
        "weightLow": (60, 180),
        "weightHigh": (-180, -60),
    },
    "RSI":{
        "interval": (7,21), # weight
        "thresholds.low": (15,45), # trend thresholds
        "thresholds.high": (45,140), # trend thresholds
        "thresholds.persistence": (4,10), # trend duration(count up by tick) thresholds
    },
    "StochRSI":{
        "interval": (7,21), # weight
        "thresholds.low": (15,45), # trend thresholds
        "thresholds.high": (45,140), # trend thresholds
        "thresholds.persistence": (4,10), # trend duration(count up by tick) thresholds
    },
    "CCI":{
        "consistant": (7,21), # constant multiplier. 0.015 gets to around 70% fit
        "history": (45,135), # history size, make same or smaller than history
        "thresholds.down": (-150,-50), # trend thresholds
        "thresholds.up": (50,150), # trend thresholds
        "thresholds.persistence": (4,10), # trend duration(count up by tick) thresholds
    },
    "UO":{
        "first.weight": (2,8), # 
        "first.period": (4.5,14), # 
        "second.weight": (1,4), # 
        "second.period": (7,28), # 
        "third.weight": (0.5,2), # 
        "third.period": (14,56), # 
        "thresholds.low": (15,45), # trend thresholds
        "thresholds.high": (45,140), # trend thresholds
        "thresholds.persistence": (0,4), # trend duration(count up by tick) thresholds
    },
    "MRBB": {
        "short": (3, 12),
        "long": (12, 32),
        "signal": (6, 23),
        "interval": (7, 23),
        "crosspersistence": (7, 30),
        "macdhigh": (0.1,0.6),
        "macdlow": (-0.6,-0.1),
        "rsihigh": (30,100),
        "rsilow": (1,35),
        "bbands.TimePeriod": (16,22),
        "bbands.NbDevUp": (1,3),
        "bbands.NbDevDn": (1,3),
        "bbands.MAType": (1,3)
	}
}


================================================
FILE: japonicus/evolution_generations.py
================================================
#!/bin/python
import json
import time
import sys

import promoterz
import evaluation

from . import interface

from .Settings import getSettings, makeSettings
import stratego
from functools import partial

import evaluation.gekko.datasetOperations as datasetOperations


StrategyFileManager = None


# TEMPORARY ASSIGNMENT OF EVAL FUNCTIONS; SO THINGS REMAIN ¿SANE;
def indicatorEvaluate(
    StrategyFileManager,
    constructPhenotype,
    genconf,
    Datasets,
    Individual,
    gekkoUrl,
):
    phenotype = constructPhenotype(Individual)
    StratName = StrategyFileManager.checkStrategy(phenotype)
    phenotype = {StratName: phenotype}
    SCORE = evaluation.gekko.backtest.Evaluate(
        genconf, Datasets, phenotype, gekkoUrl
    )
    return SCORE


def standardEvaluate(constructPhenotype,
                     genconf, Datasets, Individual, gekkoUrl):
    phenotype = constructPhenotype(Individual)
    phenotype = {Individual.Strategy: phenotype}
    SCORE = evaluation.gekko.backtest.Evaluate(
        genconf, Datasets, phenotype, gekkoUrl
    )
    return SCORE


def benchmarkEvaluate(constructPhenotype,
                      genconf, Datasets, Individual, gekkoUrl):
    phenotype = constructPhenotype(Individual)
    phenotype = {Individual.Strategy: phenotype}
    SCORE = evaluation.benchmark.benchmark.Evaluate(
        genconf, phenotype
    )
    return SCORE


def grabDatasets(conf):
    # CHECK HOW MANY EVOLUTION DATASETS ARE SPECIFIED AT SETTINGS;
    evolutionDatasetNames = ['dataset_source']
    evolutionDatasets = []
    for DS in range(1, 100):
        datasetConfigName = 'dataset_source%i' % DS
        if datasetConfigName in conf.dataset.__dict__.keys():
            evolutionDatasetNames.append(datasetConfigName)

    # --GRAB PRIMARY (EVOLUTION) DATASETS
    for evolutionDatasetName in evolutionDatasetNames:
        D = evaluation.gekko.dataset.selectCandlestickData(
            conf.Global.GekkoURLs[0],
            exchange_source=conf.dataset.__dict__[evolutionDatasetName],
            minDays=conf.backtest.deltaDays
        )
        evolutionDatasets.append(datasetOperations.CandlestickDataset(*D))
        try:
            evolutionDatasets[-1].restrain(conf.dataset.dataset_span)
        except Exception:
            print(
                'dataset_ span not configured for evolutionDatasetName. skipping...')

    # --GRAB SECONDARY (EVALUATION) DATASET
    try:
        Avoid = evolutionDatasets[0].specifications['asset']
        D = evaluation.gekko.dataset.selectCandlestickData(
            conf.Global.GekkoURLs[0],
            exchange_source=conf.dataset.eval_dataset_source,
            avoidCurrency=None,
            minDays=conf.backtest.deltaDays
        )
        if D is not None:
            evaluationDatasets = [datasetOperations.CandlestickDataset(*D)]
            evaluationDatasets[0].restrain(conf.dataset.eval_dataset_span)
        else:
            evaluationDatasets = []
    except RuntimeError:
        evaluationDatasets = []
        print("Evaluation dataset not found.")

    return evolutionDatasets, evaluationDatasets


def Generations(
        EvaluationModule,
        japonicusOptions,
        EvaluationMode,
        settings,
        options,
        web=None):

    # --LOAD SETTINGS;
    conf = makeSettings(settings)

    # --APPLY COMMAND LINE GENCONF SETTINGS;
    for parameter in conf.generation.__dict__.keys():
        if parameter in options.__dict__.keys():
            if options.__dict__[parameter] != None:
                conf.generation[parameter] = options.__dict__[parameter]

    GenerationMethod = promoterz.functions.selectRepresentationMethod(
        japonicusOptions["GenerationMethod"]
    )

    # --MANAGE Evaluation Modes;
    if EvaluationMode == 'indicator':
        # global StrategyFileManager
        StrategyFileManager = stratego.gekko_strategy.StrategyFileManager(
            conf.Global.gekkoPath, conf.indicator
        )
        Evaluate = partial(indicatorEvaluate, StrategyFileManager)
        Strategy = options.skeleton
    # --for standard methods;
    else:
        Strategy = EvaluationMode
        if options.benchmarkMode:
            Evaluate = benchmarkEvaluate
            evolutionDatasets, evaluationDatasets = [], []
            conf.gen.minimumProfitFilter = None
        else:
            Evaluate = standardEvaluate
            evolutionDatasets, evaluationDatasets = grabDatasets(
                conf
            )

    # -- PARSE TARGET PARAMETERS
    TargetParameters = promoterz.parameterOperations.flattenParameters(
        japonicusOptions["TargetParameters"])
    TargetParameters = promoterz.parameterOperations.parameterValuesToRangeOfValues(
        TargetParameters, conf.generation.parameter_spread
    )
    GlobalTools = GenerationMethod.getToolbox(Strategy,
                                              conf.generation,
                                              TargetParameters)
    RemoteHosts = evaluation.gekko.API.loadHostsFile(conf.Global.RemoteAWS)
    conf.Global.GekkoURLs += RemoteHosts
    if RemoteHosts:
        print("Connected Remote Hosts:\n%s" % ('\n').join(RemoteHosts))
        if EvaluationMode == 'indicator':
            exit('Indicator mode is yet not compatible with multiple hosts.')

    # --INITIALIZE LOGGER;
    todayDate = time.strftime("%Y_%m_%d-%H.%M.%S", time.gmtime())
    if evolutionDatasets:
        ds_specs = evolutionDatasets[0].specifications
        logfilename = "%s-%s-%s-%s-%s" % (
            Strategy,
            ds_specs['exchange'],
            ds_specs['currency'],
            ds_specs['asset'],
            todayDate
        )
    else:
        logfilename = "benchmark%s" % todayDate
    Logger = promoterz.logger.Logger(logfilename)

    # --PRINT RUNTIME ARGS TO LOG HEADER;
    ARGS = ' '.join(sys.argv)
    Logger.log(ARGS, target='Header')

    # --SHOW PARAMETER INFO;
    if Strategy:
        Logger.log("Evolving %s strategy;\n" % Strategy)
    Logger.log("evaluated parameters ranges:", target="Header")
    for k in TargetParameters.keys():
        Logger.log(
            "%s%s%s\n" % (k, " " * (30 - len(k)), TargetParameters[k]),
            target="Header"
        )

    # --LOG CONFIG INFO;
    configInfo = json.dumps(conf.generation.__dict__, indent=4)
    Logger.log(configInfo, target="Header", show=False)

    # --SHOW DATASET INFO;
    EvaluationModule.showPrimaryInfo(Logger,
                                     evolutionDatasets,
                                     evaluationDatasets)

    # --INITIALIZE WORLD WITH CANDLESTICK DATASET INFO; HERE THE GA KICKS IN;
    GlobalTools.register('Evaluate', Evaluate,
                         GlobalTools.constructPhenotype, conf.backtest)
    GlobalTools.register("ApplyResult", EvaluationModule.ResultToIndividue)
    GlobalTools.register("showIndividue", EvaluationModule.showIndividue)

    # --THIS LOADS A DATERANGE FOR A LOCALE;
    if options.benchmarkMode:
        def onInitLocale(World):
            Dataset = [
                datasetOperations.CandlestickDataset(
                    {},
                    {
                        'from': 0,
                        'to': 0
                    }
                )]
            return Dataset
    else:
        def onInitLocale(World):
            Dataset = datasetOperations.getLocaleDataset(World)
            return Dataset

    # Select run loops;
    populationLoops = [promoterz.sequence.locale.standard_loop.execute]
    worldLoops = [promoterz.sequence.world.parallel_world.execute]

    # Initalize World;
    World = promoterz.world.World(
        GlobalTools=GlobalTools,
        populationLoops=populationLoops,
        worldLoops=worldLoops,
        conf=conf,
        TargetParameters=TargetParameters,
        EnvironmentParameters={
            'evolution':  evolutionDatasets,
            'evaluation': evaluationDatasets
        },
        onInitLocale=onInitLocale,
        web=web,
    )
    World.logger = Logger
    World.EvaluationStatistics = []

    World.EvaluationModule = EvaluationModule
    World.seedEnvironment()

    World.logger.updateFile()

    # INITALIZE EVALUATION PROCESSING POOL
    World.parallel = World.EvaluationModule.EvaluationPool(
        World,
        conf.Global.GekkoURLs,
        conf.backtest.ParallelBacktests,
        conf.generation.showIndividualEvaluationInfo,
        )

    # --GENERATE INITIAL LOCALES;
    for l in range(conf.generation.NBLOCALE):
        World.generateLocale()

    # --RUN EPOCHES;
    while World.EPOCH < World.conf.generation.NBEPOCH:
        World.runEpoch()
        if conf.evalbreak.evaluateSettingsPeriodically and not options.benchmarkMode:
            if not World.EPOCH % conf.evalbreak.evaluateSettingsPeriodically:
                promoterz.evaluationBreak.showResults(World)
        if not World.EPOCH % 10:
            print("Total Evaluations: %i" % World.totalEvaluations)

    # RUN ENDS. SELECT INDIVIDUE, LOG AND PRINT STUFF;
    # FinalBestScores.append(Stats['max'])
    print(World.EnvironmentParameters)
    # After running EPOCHs, select best candidates;
    if not options.benchmarkMode:
        promoterz.evaluationBreak.showResults(World)
    print("")
    print("\t\t.RUN ENDS.")


================================================
FILE: japonicus/halt.py
================================================
#!/bin/python

import signal
import sys

import psutil
import os
import time

M = sys.version_info.major
m = sys.version_info.minor
if not M >= 3 or not m >= 6:
    message = 'check your python version before running japonicus.'
    message += ' Python>=3.6 is required. Python==%i.%i detected.' % (M, m)
    print(message)
    exit(1)


Aware = False


def userExit(x, y):

    parent = psutil.Process(os.getpid())
    global Aware
    if not Aware:
        print("\n\nAborted by user. (SIGINT)\n\n")
        Aware = True
    try:
        for child in parent.children(recursive=True): 
            child.kill()
        time.sleep(2)
        exit(0)
    except (SystemExit):
        raise


signal.signal(signal.SIGINT, userExit)


================================================
FILE: japonicus/interface.py
================================================
#!/bin/python
import evaluation



def showTitleDisclaimer(backtestsettings, VERSION):
    TITLE = """
        ██╗ █████╗ ██████╗  ██████╗ ███╗   ██╗██╗ ██████╗██╗   ██╗███████╗
        ██║██╔══██╗██╔══██╗██╔═══██╗████╗  ██║██║██╔════╝██║   ██║██╔════╝
        ██║███████║██████╔╝██║   ██║██╔██╗ ██║██║██║     ██║   ██║███████╗
   ██   ██║██╔══██║██╔═══╝ ██║   ██║██║╚██╗██║██║██║     ██║   ██║╚════██║
   ╚█████╔╝██║  ██║██║     ╚██████╔╝██║ ╚████║██║╚██████╗╚██████╔╝███████║
    ╚════╝ ╚═╝  ╚═╝╚═╝      ╚═════╝ ╚═╝  ╚═══╝╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
    """

    TITLE += "\t EVOLUTIONARY GENETIC ALGORITHMS"

    try:
        print(TITLE, end="")
    except UnicodeEncodeError or SyntaxError:
        print("\nJAPONICUS\n")
    print('\t' * 4 + 'v%.2f' % VERSION)
    print()

    profitDisclaimer = "The profits reported here depends on backtest interpreter function;"
    interpreterFuncName = backtestsettings['interpreteBacktestProfit']
    interpreterInfo = evaluation.gekko.backtest.getInterpreterBacktestInfo(
        interpreterFuncName)

    print("%s \n\t%s\n" % (profitDisclaimer, interpreterInfo))



================================================
FILE: japonicus/japonicus.py
================================================
#!/bin/python

from . import halt, Settings, interface

from time import sleep
import random
from threading import Thread

from .evolution_generations import Generations


import datetime
import os

import waitress

import promoterz
from version import VERSION


def launchWebEvolutionaryInfo():
    print("WEBSERVER MODE")
    webpageTitle = "japonicus evolutionary statistics - v%.2f" % VERSION
    webApp, webServer = promoterz.webServer.core.build_server(webpageTitle)

    webServerProcess = Thread(
        target=waitress.serve,
        kwargs={
            "app": webServer,
            "listen": "0.0.0.0:8182"
        }
    )

    webServerProcess.start()
    return webApp


def buildSettingsOptions(optionparser, settingSubsets):
    settings = Settings.getSettings(SettingsFiles=settingSubsets)

    # PARSE GENCONF & DATASET COMMANDLINE ARGUMENTS;
    for settingSubset in settingSubsets:
        parser = promoterz.metaPromoterz.generateCommandLineArguments(
            optionparser,
            settings[settingSubset])

    options, args = parser.parse_args()
    for settingSubset in settingSubsets:
        settings[settingSubset] =\
            promoterz.metaPromoterz.applyCommandLineOptionsToSettings(
            options,
            settings[settingSubset]
        )

    return settings, options


def loadEvaluationModule():

    req = [
        "validateSettings",
        "showStatistics"
    ]
    pass


class JaponicusSession():

    def __init__(self, EvaluationModule, settings, options):

        # ADDITIONAL MODES;
        markzero_time = datetime.datetime.now()

        print()

        # show title;
        interface.showTitleDisclaimer(settings['backtest'], VERSION)

        self.web_server = launchWebEvolutionaryInfo()\
            if options.spawn_web else None
        sleep(1)

        if not EvaluationModule.validateSettings(settings):
            exit(1)

        # --SELECT STRATEGY;
        if options.random_strategy:
            Strategy = ""
            GekkoStrategyFolder = os.listdir(settings['Global']['gekkoPath'] + '/strategies')
            while Strategy + '.js' not in GekkoStrategyFolder:
                if Strategy:
                    print(
                        "Strategy %s descripted on settings but not found on strat folder." %
                        Strategy
                    )
                Strategy = random.choice(list(settings['strategies'].keys()))
                print("> %s" % Strategy)
        elif options.strategy:
            Strategy = options.strategy
        elif not options.skeleton:
            print("No strategy specified! Use --strat or go --help")
            exit(1)

        # --LAUNCH GENETIC ALGORITHM;
        if options.genetic_algorithm:

            japonicusOptions = {
                "GenerationMethod": None,
                "TargetParameters": None
            }

            japonicusOptions["GenerationMethod"] =\
                'chromosome' if options.chromosome_mode else 'oldschool'

            if options.skeleton:
                EvaluationMode = 'indicator'
                AllIndicators = Settings.getSettings()['indicators']
                TargetParameters = Settings.getSettings()['skeletons'][options.skeleton]
                for K in AllIndicators.keys():
                    if type(AllIndicators[K]) != dict:
                        TargetParameters[K] = AllIndicators[K]
                    elif AllIndicators[K]['active']:
                        TargetParameters[K] = AllIndicators[K]
                        TargetParameters[K]['active'] = (0, 1)

                japonicusOptions["TargetParameters"] = TargetParameters

                if not TargetParameters:
                    print("Bad configIndicators!")
                    exit(1)
            else:
                EvaluationMode = Strategy
                # READ STRATEGY PARAMETER RANGES FROM TOML;
                try:
                    TOMLData = promoterz.TOMLutils.preprocessTOMLFile(
                        "strategy_parameters/%s.toml" % Strategy
                    )
                except FileNotFoundError:
                    print("Failure to find strategy parameter rules for " +
                          "%s at ./strategy_parameters" % Strategy)
                    gekkoParameterPath = "%s/config/strategies/%s.toml" %\
                                         (settings['Global']['gekkoPath'], Strategy)
                    print("Trying to locate strategy parameters at %s" %
                          gekkoParameterPath)

                    TOMLData = promoterz.TOMLutils.preprocessTOMLFile(
                        gekkoParameterPath)

                japonicusOptions["TargetParameters"] =\
                    promoterz.TOMLutils.TOMLToParameters(TOMLData)

            # RUN ONE EQUAL INSTANCE PER REPEATER NUMBER SETTINGS,
            # SEQUENTIALLY...
            for s in range(options.repeater):
                Generations(
                    EvaluationModule,
                    japonicusOptions,
                    EvaluationMode,
                    settings,
                    options,
                    web=self.web_server
                )

        deltatime = datetime.datetime.now() - markzero_time
        print("Run took %i seconds." % deltatime.seconds)
        if options.spawn_web:
            print('Statistics info server still runs...')




================================================
FILE: japonicus/options.py
================================================

import optparse

parser = optparse.OptionParser()
parser.add_option(
    '-g', '--genetic', dest='genetic_algorithm', action='store_true', default=False,
    help="Genetic Algorithm evolution mode."
)
parser.add_option(
    '-c', '--chromosome', dest='chromosome_mode', action='store_true', default=False,
    help="Alternative internal representation of parameters for Genetic Algorithm mode."
)
parser.add_option(
    '-b', '--bayesian', dest='bayesian_optimization', action='store_true', default=False,
    help='Bayesian evolution mode.'
)
parser.add_option(
    '-k', '--gekko', dest='spawn_gekko', action='store_true', default=False,
    help="Launch gekko instance."

)
parser.add_option(
    '-r', '--random', dest='random_strategy', action='store_true', default=False,
    help="Run on random strategy."
)
parser.add_option(
    '-e', '--benchmark', dest='benchmarkMode', action='store_true',
    default=False,
    help="Run GA benchmark mode. Strategy names are restricted to specific strats."
)
parser.add_option(
    '-w', '--web', dest='spawn_web', action='store_true', default=False,
    help="Launch japonicus web server showing evolutionary statistics."
)
parser.add_option('--repeat <x>', dest='repeater', type=int, default=1)
parser.add_option('--strat <strat>', dest='strategy', default=None)
parser.add_option('--skeleton <skeleton>', dest='skeleton', default=None)


================================================
FILE: japonicus-run
================================================
#!/bin/python
import os

import japonicus
import evaluation
os.chdir(os.path.dirname(os.path.realpath(__file__)))


settings, options = japonicus.buildSettingsOptions(
    japonicus.options.parser,
    evaluation.gekko.SettingsFiles
)
japonicus.JaponicusSession(evaluation.gekko, settings, options)


================================================
FILE: jlivetrader.py
================================================
#!/bin/python
import os
import optparse
import json

import livetrader.exchangeMonitor
import livetrader.gekkoTrigger
import livetrader.gekkoChecker

try:
    import livetrader.strategyRanker
except Exception:
    pass

parser = optparse.OptionParser()

parser.add_option('-b', '--balance',
                  dest='balanceChecker', action='store_true', default=False)

parser.add_option('-t', '--trigger <strategy>',
                  dest='botTrigger', type='str', default='')

parser.add_option('-c', dest='runningBotChecker',
                  action='store_true', default=False)

parser.add_option('-l', dest='tradingBot', action='store_true',
                  default=False)

parser.add_option('--candleSize <cs>',
                  dest='candleSize', type='int', default=5)

parser.add_option('--strat <strategy>', dest='strategy',
                  type='str', default='')

parser.add_option('--param <parameters>', dest='alternativeParameters',
                  type='str', default=None)

parser.add_option('-k', dest='killGekkoBots', action='store_true',
                  default=False,
                  help='Destroy all running gekko bot instances.')

parser.add_option('-s', dest='viewLastTrades', action='store_true',
                  default=False,
                  help='Show last trades done by bots.')

options, args = parser.parse_args()


if __name__ == '__main__':
    os.chdir(os.path.dirname(os.path.realpath(__file__)))
    exchange = livetrader.exchangeMonitor.Exchange('binance')

    if options.balanceChecker:
        totalUSD = exchange.getUserBalance()

        print("net weight at %s: US$T%.2f" % (
            exchange.name,
            totalUSD)
        )

    if options.botTrigger:
        allPairs = exchange.getAssets()
        assetCurrencyPairs = exchange.parseAssets(allPairs)
        Stratlist = [options.botTrigger]

        exchangeConfPath =\
            exchange.conf.binanceAssetCurrencyTargetFilePath
        if exchangeConfPath:
            exchangeMarketData = exchange.generateMarketsJson(
                assetCurrencyPairs)
            exchangeConfPath = os.path.join(exchangeConfPath,
                                            'binance-markets.json')

            with open(exchangeConfPath, 'w') as F:
                json.dump(exchangeMarketData, F, indent=2)

        livetrader.gekkoTrigger.launchBatchTradingBots(
            assetCurrencyPairs,
            Stratlist,
            options
        )

    if options.runningBotChecker:
        ranker = livetrader.strategyRanker.strategyRanker()
        ranker.loadStrategyRankings()
        userOrderHistory = exchange.getRecentOrders()
        for M in userOrderHistory.keys():
            marketOrderHistory = userOrderHistory[M]
            if marketOrderHistory:
                information = json.dumps(marketOrderHistory, indent=2)
                print(information)

        livetrader.gekkoChecker.checkGekkoRunningBots(exchange,
                                                      ranker, options)
    if options.killGekkoBots:
        livetrader.gekkoChecker.stopGekkoBots()

    if options.viewLastTrades:
        Orders = exchange.getRecentOrders()
        print(json.dumps(Orders, indent=2))




================================================
FILE: livetrader/exchangeMonitor.py
================================================
#!/bin/python
import ccxt
import json
from japonicus import Settings
import time


class Exchange():
    def __init__(self, name):
        self.name = name
        self.conf = Settings.makeSettings(Settings.loadTomlSettings(name))
        secret = open(self.conf.credentialsFilePath).read()
        secret = secret.split('\n')
        self.API = ccxt.binance({
            'apiKey': secret[0],
            'secret': secret[1]
        })
        self.API.load_markets()

    def getCotations(self):
        return self.fetchAssetPrices(self.getMarketsOfCurrency())

    def parseAsset(self, Asset):
        P = [float(Asset[code]) for code in ['free', 'locked']]
        return P[0], P[1]

    def fetchAssetPrices(self, Symbols):
        Prices = {}
        for Symbol in Symbols:
            Cotation = self.API.fetch_ticker(Symbol)
            Prices[Symbol] = float(Cotation['info']['lastPrice'])

        return Prices

    def getAveragePrices(self):
        Cotations = self.getCotations()
        AllCotations = list(Cotations.keys())

        averagePrices = sum([Cotations[S] for S in AllCotations]) / len(AllCotations)
        return averagePrices

    def getMarketsOfCurrency(self, currency='USDT'):
        return [S for S in self.API.symbols if '/%s' % currency in S]

    def getUserBalance(self, Verbose=False):
        Balance = self.API.fetch_balance()['info']['balances']
        totalUSD = 0
        Cotations = self.getCotations()

        for Asset in Balance:
            Free, Locked = self.parseAsset(Asset)
            if Free or Locked:
                if Verbose:
                    print(Asset)
                if Asset['asset'] == 'USDT':
                    Symbol = 'USDT'
                    totalAsset = Free + Locked
                    assetValue = totalAsset
                    if Verbose:
                        print("%.2f USDT" % totalAsset)
                else:
                    Symbol = '%s/USDT' % Asset['asset']
                    if Symbol in self.API.symbols:
                        price = Cotations[Symbol]
                        if Verbose:
                            print("%s price %.2f" % (Asset['asset'], price))
                        totalAsset = Free + Locked
                        assetValue = (totalAsset * price)
                    else:
                        continue

                totalUSD += assetValue
                if Verbose:
                    print('--')
                    print(totalAsset)
                    print(assetValue)
                    print(totalUSD)
                    print()

        return totalUSD

    def getAssets(self):
        Assets = [A for A in self.API.symbols if 'USDT' in A]
        return Assets

    def parseAssets(self, assets):
        LIST = []
        for Asset in assets:
            N = Asset.split('/')
            A = {
                'EXCHANGE': self.name,
                'ASSET': N[0],
                'CURRENCY': N[1]
            }
            LIST.append(A)

        return LIST

    def generateMarketsJson(self, Assets):
        Assets = self.getAssets()
        marketData = []
        assetList = []
        exchangeAssetInfo = self.API.publicGetExchangeInfo()['symbols']

        for Asset in Assets:
            pair = Asset.split('/')
            assetList.append(pair[0])
            pair.reverse()
            orderInfo = None
            for pairInfo in exchangeAssetInfo:
                if pairInfo['symbol'] == Asset.replace('/', ''):
                    allFilters = {}

                    for Filter in pairInfo['filters']:
                        del Filter['filterType']
                        allFilters.update(Filter)

                    orderInfo = {
                        "amount": allFilters['minQty'],
                        "price": allFilters['minPrice'],
                        "order": 1
                    }

                    break

            if orderInfo is None:
                print("Failed to grab data for %s" % Asset)
                continue

            pairEntry = {
                "pair": pair,
                "minimalOrder": orderInfo
            }

            marketData.append(pairEntry)

        fullMarketData = {
            "assets": assetList,
            "currencies": ["USDT"],
            "markets": marketData
        }

        return fullMarketData

    def getRecentOrders(self, pastTimeRangeDays=2):
        userOrderHistory = {}
        for Market in self.getAssets():
            pastTimeRange = pastTimeRangeDays * 24 * 3600
            sinceTimestamp = (time.time() - pastTimeRange) * 1000
            Orders = self.API.fetch_my_trades(Market, since=sinceTimestamp)

            userOrderHistory[Market] = Orders

        return userOrderHistory

    def getPriceHistory(self):
        candlestickData = {}
        for Market in self.getAssets():
            candlestickData[Market] = self.API.fetch_ohlcv(Market)

        return candlestickData


================================================
FILE: livetrader/gekkoChecker.py
================================================
#!/bin/python

from . import gekkoTrigger

try:
    from . import assetAllocator
except Exception:
    pass

from dateutil import parser as dateparser
import datetime
import csv
import re
import random
from subprocess import Popen, PIPE

import pytoml
import os
import time
import json


def calculateMostIndicatedAssets(exchange):
    candlestickData = exchange.getPriceHistory()
    Assets = assetAllocator.selectMostProbableAssets(candlestickData)
    Assets = [{'EXCHANGE': exchange.name,
               'ASSET': a.split('/')[0],
               'CURRENCY': a.split('/')[1]} for a in Assets]
    return Assets


def stopGekkoBots():
    PS = ['ps', 'aux']

    runningProcs = Popen(PS,
                         stdout=PIPE, stderr=PIPE)
    runningProcs = runningProcs.stdout.read().decode('utf-8').split('\n')
    killPIDs = []

    for proc in runningProcs:
        if 'gekko/core' in proc:
            PID = re.findall("\d\d\d+", proc)[0]
            killPIDs.append(PID)

    print(killPIDs)

    for PID in killPIDs:
        N = Popen(['kill', '-9', PID], stdout=PIPE)
        N.communicate()


def interpreteRunningBotStatistics(runningBots):
    allBotStrategies = []
    runningTimes = []

    for B in runningBots.keys():
        Bot = runningBots[B]

        if Bot["config"]["type"] == 'tradebot':
            botCurrentStrategy = Bot["config"]["tradingAdvisor"]["method"]
            allBotStrategies.append(botCurrentStrategy)

        elif Bot["config"]["type"] == 'market watcher':
            fC = dateparser.parse(Bot["events"]["initial"]["candle"]["start"])
            lC = dateparser.parse(Bot["events"]["latest"]["candle"]["start"])
            delta = (lC - fC).seconds

            runningTime = delta
            runningTimes.append(runningTime)

        else:
            print("Odd runningBot found:")
            print(json.dumps(Bot, indent=2))

    return runningTimes, allBotStrategies


def getParameterSettingsPath(parameterName):
    N = os.path.join('strategy_parameters',
                     parameterName) + '.toml'
    return N


def operateStrategyScores(exchange, ranker,
                          Balances, runningTimeHours,
                          currentPortfolioStatistics, runningBotStrategies):
    print("Rebooting gekko trading bots.")

    markzeroTime = datetime.timedelta(minutes=runningTimeHours*3600)
    predictedStartTime = datetime.datetime.now() - markzeroTime
    # APPLY LAST SCORE TO STRATEGIES;
    ranker.loadStrategyRankings()

    def makeBalanceScore(entry):
        return (float(entry['BALANCE']) /
                float(entry['AVERAGE_PRICE']))

    pastCorrespondingScore = None
    for row in Balances:
        balanceDate = dateparser.parse(row['TIME'])
        timeDelta = predictedStartTime - balanceDate
        minuteDelta = abs(timeDelta.seconds) / 60
        if minuteDelta < 60:
            pastCorrespondingScore = makeBalanceScore(row)

    if pastCorrespondingScore is not None:
        currentScore =\
            makeBalanceScore(currentPortfolioStatistics)

        botRunScore = currentScore / pastCorrespondingScore * 100
        normalizedBotRunScore = botRunScore / runningTimeHours

        runningStrategy = None
        for Strategy in ranker.Strategies:
            equalStrats = True
            strategyParameters = pytoml.load(open(
                getParameterSettingsPath(Strategy.parameters)))
            print(runningBotStrategies[-1])
            comparateParameters =\
                runningBotStrategies[-1]['params']
            for param in comparateParameters.keys():
                if type(param) == dict:
                    continue
                if param not in strategyParameters.keys():
                    equalStrats = False
                    break
                if strategyParameters[param] !=\
                   comparateParameters[param]:
                    equalStrats = False
                    break
            if equalStrats:
                runningStrategy = Strategy
                break

        if runningStrategy:
            print("Runnnig strategy found at scoreboard.")
            runningStrategy.profits.append(normalizedBotRunScore)
        else:
            print("Running strategy not found at scoreboard.")

    # WRITE NEW STRATEGY SCORES;
    ranker.saveStrategyRankings()


def checkGekkoRunningBots(exchange, ranker, options):
    runningBots = gekkoTrigger.getRunningGekkos()

    BalancesFields = ['TIME', 'BALANCE', 'AVERAGE_PRICE']

    selectorSigma = exchange.conf.strategySelectorSigma
    allPairs = exchange.getAssets()
    assetCurrencyPairs = exchange.parseAssets(allPairs)

    try:
        Balances = csv.DictReader(open('balances.csv'))
    except FileNotFoundError:
        print("Balances file not found.")
        Balances = []

    Balances = [row for row in Balances]
    wBalances = csv.DictWriter(open('balances.csv', 'w'),
                               fieldnames=BalancesFields)
    wBalances.writeheader()
    for N in Balances:
        wBalances.writerow(N)

    currentPortfolioValue = exchange.getUserBalance()
    print("Net weight %.2f USD" % currentPortfolioValue)

    currentPortfolioStatistics = {
        'TIME': str(datetime.datetime.now()),
        'BALANCE': currentPortfolioValue,
        'AVERAGE_PRICE': exchange.getAveragePrices()
    }

    wBalances.writerow(currentPortfolioStatistics)

    if runningBots:
        runningTimes, runningBotStrategies =\
            interpreteRunningBotStatistics(runningBots)

        if runningTimes and runningBotStrategies:
            averageRunningTime = sum(runningTimes) / len(runningTimes)
            runningTimeHours = averageRunningTime / 3600

            targetMinimumRunningHours =\
                exchange.conf.strategyRunTimePeriodHours

            # if target running time is reached;
            if runningTimeHours > targetMinimumRunningHours:
                operateStrategyScores(exchange, ranker,
                                      Balances, runningTimeHours,
                                      currentPortfolioStatistics,
                                      runningBotStrategies)

                Strategy = ranker.selectStrategyToRun(selectorSigma)

                stopGekkoBots()
                time.sleep(60)

                selectedAssetCurrencyPairs = calculateMostIndicatedAssets(exchange)
                gekkoTrigger.launchBatchTradingBots(
                    selectedAssetCurrencyPairs,
                    [Strategy.strategy],
                    options
                )

            else:
                print("Target runtime not reached.")
    else:
        ranker.loadStrategyRankings()
        print("Launching bots on idle gekko instance.")
        Strategy = ranker.selectStrategyToRun(selectorSigma)
        selectedAssetCurrencyPairs = calculateMostIndicatedAssets(exchange)
        print(assetCurrencyPairs)
        print(selectedAssetCurrencyPairs)
        gekkoTrigger.launchBatchTradingBots(
            selectedAssetCurrencyPairs,
            [Strategy.strategy],
            options
        )


================================================
FILE: livetrader/gekkoTrigger.py
================================================
#!/bin/python
import time
from evaluation.gekko.API import httpPost
from evaluation.gekko.dataset import epochToString
import requests
import json
from promoterz import TOMLutils


def runTradingBot(botSpecifications, Strategy, options, TradingBot=False):
    URL = "http://localhost:3000/api/startGekko"

    if not Strategy:
        Strategy = botSpecifications['STRATEGY']

    print("Starting bot running %s for %s/%s at %s." % (
        Strategy,
        botSpecifications['ASSET'],
        botSpecifications['CURRENCY'],
        botSpecifications['EXCHANGE']))

    traderParameters = {
        "tradingAdvisor": {
            "enabled": 'true',
            "method": Strategy,
            "candleSize": options.candleSize,
            "historySize": 40
        }
    }

    watchSettings = getWatchSettings(botSpecifications)
    traderParameters.update(getTraderBaseParameters())
    traderParameters.update(watchSettings)

    if TradingBot:
        traderParameters['type'] = "tradebot"
        traderParameters['trader'] = {'enabled': 'true'}
    else:
        traderParameters['type'] = "paper trader"
        traderParameters['paperTrader'] = {
            "feeMaker": 0.25,
            "feeTaker": 0.25,
            "feeUsing": "maker",
            "slippage": 0.05,
            "simulationBalance": {
                "asset": 0,
                "currency": 100
            },
            "reportRoundtrips": 'true',
            "enabled": 'true'
        }

    commonPath = 'strategy_parameters/%s.toml'
    if options.alternativeParameters:
        parameterPath = commonPath % options.alternativeParameters
    else:
        parameterPath = commonPath % Strategy

    strategySettings = TOMLutils.preprocessTOMLFile(
        parameterPath)
    strategySettings = TOMLutils.TOMLToParameters(strategySettings)
    traderParameters[Strategy] = strategySettings

    watcherSettings = getWatcherBaseParameters()
    watcherSettings.update(watchSettings)

    ExistingWatcher = checkWatcherExists(watchSettings)
    if not ExistingWatcher:
        print("Creating watcher for %s!" %
              watchSettings['watch']['exchange'])
        Watcher = httpPost(URL, watcherSettings)
        time.sleep(4)
    else:
        print("Watcher for %s-%s exists! Creating none." %
              (watchSettings['watch']['exchange'],
              watchSettings['watch']['asset']))
        Watcher = None
        traderParameters

    Trader = httpPost(URL, traderParameters)

    return Watcher, Trader


def getTraderBaseParameters():
    Request = {
        "market": {
            "type": "leech",
            "from": epochToString(time.time())
        },
        "mode": "realtime",
        "adviceWriter" : {
            "enabled": 'false',
            "muteSoft": 'false'
            },
        "adviceLogger": {
            "enabled": 'false',
            "muteSoft": 'false'
            },

        "candleWriter": {
            "enabled": 'false',
            "adapter": "sqlite"
        },
        "type": "paper trader",
        "performanceAnalyzer": {
            "riskFreeReturn": 2,
            "enabled": 'false'
        },
        "valid": 'true'
    }
    return Request


def getWatchSettings(coinInfo):
    W = {
        "watch": {
            "exchange": coinInfo["EXCHANGE"],
            "currency": coinInfo["CURRENCY"].upper(),
            "asset": coinInfo["ASSET"].upper()
        }
    }
    return W


def checkWatcherExists(Watch):
    gekkoInstances = getRunningGekkos()
    Watch = Watch['watch']
    checkKeys = ['asset', 'currency', 'exchange']
    for instanceName in gekkoInstances.keys():
        instance = gekkoInstances[instanceName]
        if instance['type'] == 'watcher':
            FOUND = True
            watcherTargetAssetCurrency = instance['config']['watch']
            for C in checkKeys:
                if watcherTargetAssetCurrency[C] != Watch[C]:
                    FOUND = False
                    break
            if FOUND:
                return instance['id']

    return False


def getRunningGekkos():
    try:
        W = requests.get('http://localhost:3000/api/gekkos')
    except requests.exceptions.ConnectionError:
        print("Gekko is not running.")
        return {}
    runningGekkos = json.loads(W.text)['live']
    return runningGekkos


def getWatcherBaseParameters():
    Request = {
        "candleWriter": {
            "enabled": "false",
            "adapter": "sqlite"
        },
        "type": "market watcher",
        "mode": "realtime"
    }
    return Request


def launchBatchTradingBots(assetCurrencyPairs, Stratlist, options):
    for assetCurrencyPair in assetCurrencyPairs:
        for Strategy in Stratlist:
            w, t = runTradingBot(assetCurrencyPair, Strategy,
                                 options, TradingBot=True)




================================================
FILE: livetrader/japonicusResultSelector.py
================================================
#!/bin/python
import os
import csv
import shutil
import names

from . import exchangeMonitor


def readResultFolder(strategyName, runLogFolderPath, retrievalCount=1):
    evalBreaksLogFilename = os.path.join(runLogFolderPath, 'evaluation_breaks.csv')
    if not os.path.isfile(evalBreaksLogFilename):
        print("Evaluation break log file not found.")
        return False

    evalBreakLogs = open(evalBreaksLogFilename)

    evalBreakLogs = csv.DictReader(evalBreakLogs)

    positiveResults = []
    for result in evalBreakLogs:
        if result['evaluation'] > 0 and result['secondary'] > 0:
            if len(list(result.keys())) > 2:
                result['score'] = result['evaluation'] + result['secondary']
                positiveResults.append(result)
            else:
                print("Naive logging system detected, from older japonicus version.")
                print("Unable to check result file.")

    if not positiveResults:
        print("No positive results found!")
        return False

    positiveResults = sorted(positiveResults,
                             key=lambda r: r['score'], reverse=True)


    parameterName = strategyName + names.get_full_name()

    R = positiveResults[0]
    stratPath = os.path.join(R['filepath'])
    shutil.copy()

    strategyRankings = exchangeMonitor.loadStrategyRankings()

    newEntry = exchangeMonitor.strategyParameterSet(
        {
            'strategy': strategyName,
            'parameters': parameterName,
            'profits': []
        }
    )

    strategyRankings.append(newEntry)

    exchangeMonitor.saveStrategyRankings(strategyRankings)
    
    return True


def sweepLogFolder():
    availableLogs = os.listdir('logs')
    for folder in availableLogs:
        print(folder)
        strategyName = ''
        readResult = readResultFolder(strategyName, folder)


================================================
FILE: livetrader/strategyRanker.py
================================================
#!/bin/python
import json
import pytoml
import random


class strategyRanker():
    def __init__(self):
        self.Strategies = []

    def loadStrategyRankings(self):
        W = json.load(open("gekkoStrategyRankings.json"))
        self.Strategies = []
        for s in W:
            S = strategyParameterSet(s)
            self.Strategies.append(S)

    def saveStrategyRankings(self):
        outputList = []

        for strategy in self.Strategies:
            outputList.append(strategy.toJson())

        json.dump(outputList, open("gekkoStrategyRankings.json", 'w'))

    def selectStrategyToRun(self, sigma=10):
        # SELECT AND LAUNCH TRADING BOT BATCH WITH SELECTED STRATEGY;
        if random.random() < sigma / 100:
            Strategy = sorted(self.Strategies,
                              key=lambda s: s.getScore(), reverse=True)[0]
        else:
            Strategy = random.choice(self.Strategies)

        return Strategy


class strategyParameterSet():
    def __init__(self, jsonData):
        self.Attributes = ['strategy', 'parameters', 'profits']
        self.fromJson(jsonData)

    def fromJson(self, jsonData):
        for Name in self.Attributes:
            self.__dict__[Name] = jsonData[Name]

    def toJson(self):
        jsonData = {}
        for Name in self.Attributes:
            jsonData[Name] = self.__dict__[Name]
        return jsonData

    def loadParameterSet(self):
        self.parameterSet = pytoml.load(open(self.parameters))

    def getScore(self):
        if self.profits:
            return sum(self.profits) / len(self.profits)
        else:
            return 0


================================================
FILE: promoterz/README.md
================================================
A python module specialized on genetic algorithms using various representations. 
Intended to evolve a dict of parameters, nested or not, provided with respective ranges.

```
sampleParameters = {'short': (6,8),
              'persist': (1,50),
              'variableY': (2,6),
              'ROP_weight': (5,7),
              'santa': (1,10),
              'thresholds': {
                 'top': (8,11),
                 'bottom': (17,32)
              },
              'IL12': (3,8)}
```


================================================
FILE: promoterz/TOMLutils.py
================================================
#!/bin/python
import re
import pytoml

def preprocessTOMLFile(filepath):
    f = open(filepath)
    return f


def TOMLToParameters(TOMLDATA):
    Parameters = pytoml.load(TOMLDATA)

    for Parameter in Parameters.keys():
        if type(Parameter) == str:
            if '=' in Parameter:
                Parameter = Parameter.replace('=', '')
                Parameter = float(Parameter)
            
    return Parameters


def parametersToTOML(Settings):
    Text = pytoml.dumps(Settings)
    
    return Text


================================================
FILE: promoterz/__init__.py
================================================
#!/bin/python
from .import functions

from .import supplement, validation, parameterOperations
from .import evolutionHooks
from .import world, locale
from .import evaluationPool
from .import logger
from .import metaPromoterz
from .import sequence
from .import webServer
from .import TOMLutils
from .import evaluationBreak


================================================
FILE: promoterz/environment.py
================================================
#!/bin/python


class Environment():
    def __init__(self, propertyGenenerator):
        self.w = None


================================================
FILE: promoterz/evaluationBreak.py
================================================
#!/bin/python
import random
import json
import csv
from deap import tools


import promoterz
import evaluation
from . import TOMLutils


def showResults(World):
    validationDatasets = []
    # IS EVALUATION DATASET LOADED? USE IT;
    if World.EnvironmentParameters['evaluation']:
        useSecondary = 'evaluation'
    else:
        useSecondary = 'evolution'

    # LOAD EVALUATION DATASET;
    sourceDataset = random.choice(World.EnvironmentParameters[useSecondary])
    getter = evaluation.gekko.datasetOperations.getRandomSectorOfDataset
    for NB in range(World.conf.evalbreak.proofSize):
        newDataset = getter(sourceDataset, World.conf.backtest.deltaDays)
        validationDatasets.append(newDataset)

    for LOCALE in World.locales:
        LOCALE.population = [ind for ind in LOCALE.population
                             if ind.fitness.valid]

        # SELECT BEST INDIVIDUALS;
        B = World.conf.evalbreak.NBBESTINDS
        BestIndividues = tools.selBest(LOCALE.population, B)
        Z = min(World.conf.evalbreak.NBADDITIONALINDS,
                len(LOCALE.population) - B)
        Z = max(0, Z)

        # SELECT ADDITIONAL INDIVIDUALS;
        AdditionalIndividues = promoterz.evolutionHooks.Tournament(
            LOCALE.population, Z, Z * 2
        )
        print("%i selected;" % len(AdditionalIndividues))
        AdditionalIndividues = [
            x for x in AdditionalIndividues if x not in BestIndividues
        ]
        setOfToEvaluateIndividues = BestIndividues + AdditionalIndividues
        print("%i selected;" % len(setOfToEvaluateIndividues))
        print("Selecting %i+%i individues, random test;" % (B, Z))

        currentSessionBreakResults = []
        # EVALAUTE EACH SELECTED INDIVIDUE;
        for FinalIndividue in setOfToEvaluateIndividues:
            GlobalLogEntry = {}
            proof = stratSettingsProofOfViability
            AssertFitness, FinalProfit, Results = proof(
                World, FinalIndividue, validationDatasets
            )
            LOCALE.lastEvaluation = FinalProfit
            GlobalLogEntry['evaluation'] = FinalProfit
            World.logger.log(
                "\n\n\nTesting Strategy of %s @ EPOCH %i:\n" % (
                    LOCALE.name,
                    LOCALE.EPOCH)
            )

            for R, Result in enumerate(Results):
                World.logger.log(
                    evaluation.gekko.showBacktestResult(Result,
                                       validationDatasets[R]) + '\n')

            World.logger.log(
                '\nRelative profit on evolution dataset: %.3f' %
                FinalProfit)
            if AssertFitness or FinalProfit > 50:
                World.logger.log("Current parameters are viable.")
            else:
                World.logger.log("Current parameters fails.")
                if not World.conf.Global.showFailedStrategies:
                    World.logger.log(
                        "Skipping further tests on current parameters.",
                        show=False)
                    continue

            FinalIndividueSettings = World.tools.constructPhenotype(
                FinalIndividue)

            # -- PREFETCH TOMLSettings;
            TOMLSettings = TOMLutils.parametersToTOML(
                FinalIndividueSettings
            )

            # --EVALUATION DATASET TEST AND REPORT;
            if World.EnvironmentParameters['evaluation']:
                evalDataset = random.choice(
                    World.EnvironmentParameters['evaluation'])
                evalDataset = getter(evalDataset, 0)
                secondaryResults = World.parallel.evaluateBackend(
                    [evalDataset], 0, [FinalIndividue]
                )
                print()
                # print(secondaryResults)
                backtestResult = secondaryResults[0][0]
                World.logger.log(
                    "Relative profit on evaluation dataset: \n\t%s" %
                    evaluation.gekko.showBacktestResult(backtestResult))
                LOCALE.lastEvaluationOnSecondary =\
                    backtestResult['relativeProfit']
                GlobalLogEntry['secondary'] =\
                    backtestResult['relativeProfit']

                currentSessionBreakResults.append((backtestResult['relativeProfit'],
                                                   TOMLSettings))
            else:
                print("Evaluation dataset is disabled.")

            # LOG AND SHOW PARAMETERS;
            Show = json.dumps(FinalIndividueSettings, indent=2)
            print("~" * 18)
            World.logger.log(" %.3f final profit ~~~~" % FinalProfit)
            print(" -- Settings for Gekko config.js -- ")
            World.logger.log(Show)
            print(" -- Settings for Gekko --ui webpage -- ")

            World.logger.log(TOMLSettings)

            paramsFilename = "%s-EPOCH%i" % (LOCALE.name,
                                             LOCALE.EPOCH)
            World.logger.saveParameters(paramsFilename, TOMLSettings)
            GlobalLogEntry['filename'] = paramsFilename
            print("\nRemember to check MAX and MIN values for each parameter.")
            print("\tresults may improve with extended ranges.")
            World.EvaluationStatistics.append(GlobalLogEntry)

    # SAVE GLOBAL EVALUATION LOGS;
    evaluationBreaksFilename = 'logs/evaluation_breaks.csv'

    if World.EvaluationStatistics:
        fieldnames = list(World.EvaluationStatistics[0].keys())
        with open(evaluationBreaksFilename, 'w') as f:
            GlobalEvolutionSummary = csv.DictWriter(f, fieldnames)
            GlobalEvolutionSummary.writeheader()
            World.logger.log('\t'.join(GlobalEvolutionSummary.fieldnames),
                             target="Summary",
                             show=False, replace=True)

            for n in World.EvaluationStatistics:
                GlobalEvolutionSummary.writerow(n)
        with open(evaluationBreaksFilename) as f:
            GlobalEvolutionSummary = csv.DictReader(f)
            for row in GlobalEvolutionSummary:
                World.logger.log('\t'.join([row[x] for x in row.keys()]),
                                 target="Summary",
                                 show=False, replace=False)

    World.logger.updateFile()

    # UPDATE WEB SERVER VISUALIZATION;
    if World.web:
        World.web.updateEvalBreakGraph(World.web, World.EvaluationStatistics)
        World.web.resultParameters += currentSessionBreakResults


def stratSettingsProofOfViability(World, Individual, Datasets):
    AllProofs = []
    # Datasets = [[x] for x in Datasets]
    Results = World.parallel.evaluateBackend(Datasets, 0, [Individual])
    for W in Results[0]:
        AllProofs.append(W['relativeProfit'])
    testMoney = 0
    for value in AllProofs:
        testMoney += value
    check = [x for x in AllProofs if x > 0]
    Valid = sum(check) == len(AllProofs)
    return Valid, testMoney, Results[0]


================================================
FILE: promoterz/evaluationPool.py
================================================
#!/bin/python
import time
import random
import itertools

from multiprocessing import Pool, TimeoutError
from multiprocessing.pool import ThreadPool


class EvaluationPool():

    def __init__(self,
                 World,
                 Urls, poolsize, individual_info):
        self.World = World

        self.Urls = Urls
        self.lasttimes = [0 for x in Urls]
        self.lasttimesperind = [0 for x in Urls]
        self.poolsizes = [poolsize for x in Urls]
        self.individual_info = individual_info

    def evaluateBackend(self, datasets, I, inds):
        stime = time.time()
        dateInds = list(itertools.product(datasets, inds))
        # print(list(dateInds))
        Q = [
            ([dataset], Ind, self.Urls[I])
            for dataset, Ind in dateInds
        ]
        P = Pool(self.poolsizes[I])
        fitnesses = P.starmap(self.World.tools.Evaluate, Q)
        P.close()
        P.join()
        delta_time = time.time() - stime
        return fitnesses, delta_time

    def evaluatePopulation(self, locale):
        individues_to_simulate = [
            ind for ind in locale.population if not ind.fitness.valid
        ]
        props = self.distributeIndividuals(individues_to_simulate)
        args = [
            [
                locale.Dataset,
                I,
                props[I],
            ]
            for I in range(len(self.Urls))
        ]
        pool = ThreadPool(len(self.Urls))
        results = []
        try:
            for A in args:
                results.append(pool.apply_async(self.evaluateBackend, A))
            pool.close()
        except (SystemExit, KeyboardInterrupt):
            print("Aborted by user.")
            exit(0)
        TimedOut = []
        for A in range(len(results)):
            try:
                perindTime = 3 * self.lasttimesperind[A]\
                             if self.lasttimesperind[A] else 12
                timeout = perindTime * len(props[A])\
                    if A else None  # no timeout for local machine;
                results[A] = results[A].get(timeout=timeout)
            except TimeoutError:  # Timeout: remote machine is dead;
                print("Machine timeouts!")
                args[A][1] = 0  # Set to evaluate @ local machine
                results[A] = self.evaluateBackend(* args[A])
                TimedOut.append(A)
        pool.join()
        TotalNumberOfTrades = 0
        for PoolIndex in range(len(results)):
            for i, fit in enumerate(results[PoolIndex][0]):
                if self.individual_info:
                    print(self.World.tools.showIndividue(fit))
                self.World.tools.ApplyResult(fit, props[PoolIndex][i])

                TotalNumberOfTrades += fit['trades']
            self.lasttimes[PoolIndex] = results[PoolIndex][1]
            L = len(props[PoolIndex])
            self.lasttimesperind[PoolIndex] =\
                self.lasttimes[PoolIndex] / L if L else 5
        F = [x.fitness.valid for x in individues_to_simulate]
        assert (all(F))
        for T in TimedOut:
            self.ejectURL(T)
        N = len(individues_to_simulate)
        # RECORD NUMBER OF EVALUATIONS;
        locale.World.totalEvaluations += N
        # CALCULATE AVERAGE TRADE NUMBER;
        averageTrades = TotalNumberOfTrades / max(1, N)
        return N, averageTrades


================================================
FILE: promoterz/evolutionHooks.py
================================================
#!/bin/python
from deap import base, tools
from copy import deepcopy

import random

import promoterz.supplement.age
import promoterz.supplement.PRoFIGA
import promoterz.supplement.phenotypicDivergence

import itertools


# population as last positional argument, to blend with toolbox;
def immigrateHoF(HallOfFame, population):
    if not HallOfFame.items:
        return population

    for Q in range(1):
        CHP = deepcopy(random.choice(HallOfFame))
        del CHP.fitness.values
        population += [CHP]
    return population


def immigrateRandom(populate, nb_range, population):  # (populate function)
    number = random.randint(*nb_range)
    population += populate(number)
    return population


def filterAwayWorst(population, N=5):
    aliveSize = len(population) - 5
    population = tools.selBest(population, aliveSize)
    return population


def filterAwayThreshold(locale, Threshold, min_nb_inds):
    thresholdFilter = lambda ind: ind.fitness.values[0] > Threshold
    populationFilter(locale, thresholdFilter, min_nb_inds)


def filterAwayTradeCounts(locale, ThresholdRange, min_nb_inds):
    def tradecountFilter(ind):
        if ind.trades < ThresholdRange[0]:
            return False
        elif ind.trades > ThresholdRange[1]:
            return False
        else:
            return True

    populationFilter(locale, tradecountFilter, min_nb_inds)


def filterAwayRoundtripDuration(locale, ThresholdRange, min_nb_inds):
    def roundtripDurationFilter(ind):
        averageExposureHours = ind.averageExposure
        if averageExposureHours < ThresholdRange[0]:
            return False
        elif averageExposureHours > ThresholdRange[1]:
            return False
        else:
            return True

    populationFilter(locale, roundtripDurationFilter, min_nb_inds)


def populationFilter(locale, filterFunction, min_nb_inds):

    newPopulation = [
        ind for ind in locale.population if filterFunction(ind)
    ]
    removed = [ind for ind in locale.population if ind not in newPopulation]

    NBreturn = min(min_nb_inds - len(locale.population),
                          min_nb_inds)
    NBreturn = max(0, NBreturn)
    if NBreturn and removed:
        for k in range(NBreturn):
            if removed:
                newPopulation.append(removed.pop(random.randrange(0,
                                                                  len(removed))))

    locale.population = newPopulation


def evaluatePopulation(locale):
    individues_to_simulate = [ind for ind in locale.population
                              if not ind.fitness.valid]
    fitnesses = locale.World.parallel.starmap(
        locale.extratools.Evaluate, zip(individues_to_simulate)
    )
    for i, fit in zip(range(len(individues_to_simulate)), fitnesses):
        individues_to_simulate[i].fitness.values = fit
    return len(individues_to_simulate)


def getLocaleEvolutionToolbox(World, locale):
    toolbox = base.Toolbox()
    toolbox.register("ImmigrateHoF", immigrateHoF, locale.HallOfFame)
    toolbox.register("ImmigrateRandom", immigrateRandom, World.tools.population)
    toolbox.register("filterThreshold", filterAwayThreshold, locale)
    toolbox.register("filterTrades", filterAwayTradeCounts, locale)
    toolbox.register("filterExposure", filterAwayRoundtripDuration, locale)
    toolbox.register('ageZero', promoterz.supplement.age.ageZero)
    toolbox.register(
        'populationAges',
        promoterz.supplement.age.populationAges,
        World.conf.generation.ageBoundaries,
    )
    toolbox.register(
        'populationPD',
        promoterz.supplement.phenotypicDivergence.populationPhenotypicDivergence,
        World.tools.constructPhenotype,
    )
    toolbox.register('evaluatePopulation', evaluatePopulation)
    return toolbox


def getGlobalToolbox(representationModule):
    # GLOBAL FUNCTION TO GET GLOBAL TBX UNDER DEVELOPMENT;
    toolbox = base.Toolbox()
    creator.create("FitnessMax", base.Fitness, weights=(1.0,))
    creator.create(
        "Individual",
        list,
        fitness=creator.FitnessMax,
        PromoterMap=None,
        Strategy=genconf.Strategy,
    )
    toolbox.register("mate", representationModule.crossover)
    toolbox.register("mutate", representationModule.mutate)
    PromoterMap = initPromoterMap(Attributes)
    toolbox.register("newind", initInd, creator.Individual, PromoterMap)
    toolbox.register("population", tools.initRepeat, list, toolbox.newind)
    toolbox.register("constructPhenotype", representationModule.constructPhenotype)
    return toolbox


def getFitness(individual):
    R = sum(individual.wvalues)


def selectCriteria(ind):
    return sum(ind.fitness.wvalues)


def selBest(individuals, number):
    chosen = sorted(individuals, key=selectCriteria, reverse=True)
    return chosen[:number]


def Tournament(individuals, finalselect, tournsize):
    chosen = []
    for i in range(finalselect):
        aspirants = tools.selRandom(individuals, tournsize)
        chosen.append(max(individuals, key=selectCriteria))
    return chosen


================================================
FILE: promoterz/evolutionToolbox.py
================================================
#!/bin/python
from deap import base


def getExtraTools(HallOfFame, W):
    T = base.Toolbox()
    T.register('q')


================================================
FILE: promoterz/functions.py
================================================
#!/bin/python
import random
from deap import base
from deap import creator
from deap import tools
from copy import deepcopy

import importlib


def PrepareAndEvaluate(constructPhenotype, evaluationMethod, Individual):
    phenotype = constructPhenotype(Individual)
    return evaluationMethod(phenotype)


def selectRepresentationMethod(methodname):
    M = importlib.import_module("promoterz.representation.%s" % methodname)
    return M


================================================
FILE: promoterz/locale.py
================================================
#!/bin/python
from deap import tools

from . import evolutionHooks
from . import statistics


class Locale():

    def __init__(self, World, name, position, loop):
        self.World = World
        self.name = name
        self.EPOCH = 0
        self.position = position
        self.EvolutionStatistics = []
        self.HallOfFame = tools.HallOfFame(30)
        self.extratools = evolutionHooks.getLocaleEvolutionToolbox(
            World, self
        )
        # GENERATION METHOD SELECTION;
        # to easily employ various GA algorithms,
        # this base EPOCH processor loads a GenerationMethod file,
        # which should contain a genToolbox function to generate
        # fully working DEAP toolbox, and a reconstructTradeSettings
        # function to convert parameters from individue to usable strategy Settings;
        # Check promoterz/representation;
        #genconf.Strategy = Strategy # ovrride strat defined on settings if needed;

        # --initial population
        self.population = World.tools.population(World.conf.generation.POP_SIZE)
        self.lastEvaluation = None
        self.lastEvaluationOnSecondary = None

        # --INIT STATISTICS;
        self.stats = statistics.getStatisticsMeter()
        self.InitialBestScores, self.FinalBestScores = [], []
        self.POP_SIZE = World.conf.generation.POP_SIZE
        self.loop = loop

    def run(self):
        print(self.name)
        self.loop(self.World, self)
        self.EPOCH += 1


================================================
FILE: promoterz/logAnalysis.py
================================================


================================================
FILE: promoterz/logger.py
================================================
#!/bin/python
import datetime
import os
import csv


class Logger():
    def __init__(self, logfilename):
        date = datetime.datetime.now()
        if not os.path.isdir('logs'):
            os.mkdir('logs')

        self.logfilename = logfilename
        self.Header = ""
        self.Summary = ""
        self.Body = ""
        self.Online = False

    def log(self, message, target="Body", show=True, replace=False):
        if target == "Body":
            # now the log has value to be written.
            if not self.Online:
                os.mkdir('logs/%s' % self.logfilename)
                os.mkdir('logs/%s/results' % self.logfilename)
            self.Online = True

        if replace:
            self.__dict__[target] = message
        else:
            self.__dict__[target] += message + '\n'
        if show:
            print(message)

    def updateFile(self):
        if not self.Online:
            return
        File = open('logs/%s/japonicus.log' % self.logfilename, 'w')
        for segment in [self.Header, self.Summary, self.Body]:
            File.write(segment + '\n')

        File.close()

    def write_evolution_logs(self, i, stats, localeName):
        filename = "logs/%s/%s.csv" % (self.logfilename, localeName)
        if stats:
            fieldnames = list(stats[0].keys())
            with open(filename, 'w') as f:
                df = csv.DictWriter(f, fieldnames)
                df.writeheader()
                df.writerows(stats)

    def saveParameters(self, filename, content):
        filename = "logs/%s/results/%s.toml" % (self.logfilename, filename)
        File = open(filename, 'w')
        File.write(content)
        File.close()


================================================
FILE: promoterz/metaPromoterz.py
================================================
#!/bin/python

# this file contains functions for 'meta genetic algorithm',
# this acts to allow settings value manipulation via command line,
# making possible a simple GA of GAs under bash.

# TBD
from .parameterOperations import flattenParameters, expandNestedParameters


def generateCommandLineArguments(parser, settings):
    flatSettings = flattenParameters(settings)
    for Setting in flatSettings.keys():
        if type(flatSettings[Setting])  in [list, bool, tuple]:
            pass
        else:
            originalValue = flatSettings[Setting]
            parameterType = type(originalValue)
            if parameterType.__name__ == 'NoneType':
                parameterType = str
            parser.add_option("--%s" % Setting,
                              dest=Setting,
                              type=parameterType.__name__,
                              default=originalValue)

    return parser


def applyCommandLineOptionsToSettings(options, settings):
    flatSettings = flattenParameters(settings)

    for Setting in flatSettings.keys():
        if Setting in options.__dict__.keys():
            flatSettings[Setting] = options.__dict__[Setting]

    Settings = expandNestedParameters(flatSettings)
    return Settings


================================================
FILE: promoterz/parameterOperations.py
================================================


#!/bin/python
def flattenParameters(Parameters):
    result = {}

    def iter(D, path= []):
        for q in D.keys():
            if type(D[q]) == dict:
                iter(D[q], path + [q])
            else:
                path_keyname = ".".join(path + [q])
                result.update({path_keyname: D[q]})

    iter(Parameters)
    return result


def expandNestedParameters(Parameters):
    _Parameters = {}
    for K in Parameters.keys():
        if '.' in K:
            Q = K.split('.')
            cursor = 0
            base = _Parameters
            while cursor < len(Q) - 1:
                if not Q[cursor] in base.keys():
                    base[Q[cursor]] = {}
                base = base[Q[cursor]]
                cursor += 1
            base[Q[cursor]] = Parameters[K]
        else:
            _Parameters[K] = Parameters[K]
    return _Parameters


def parameterValuesToRangeOfValues(TargetParameters, Spread):
    for parameter in TargetParameters.keys():
        P = TargetParameters[parameter]
        if type(P) not in [tuple, list]:
            spread_change = Spread * P / 200
            if P < 0:
                spread_change = -spread_change
            TargetParameters[parameter] = (P - spread_change, P + spread_change)
    return TargetParameters


================================================
FILE: promoterz/representation/Creator.py
================================================
#!/bin/python
from .import deapCreator as creator
from deap import base


def init(fitness, extraParameters):
    creator.create("FitnessMax", fitness, weights=(1.0, 1))
    creator.create("Individual", list, fitness=creator.FitnessMax, **extraParameters)
    return creator


================================================
FILE: promoterz/representation/chromosome.py
================================================
#!/bin/python
from deap import base
from deap import tools

from copy import deepcopy
import random

from . .import parameterOperations

from .import Creator

getPromoterFromMap = lambda x: [x[z] for z in list(x.keys())]


def constructPhenotype(stratSettings, chrconf, Individue):
    Settings = {}
    GeneSize = 2
    R = lambda V, lim: (lim[1] - lim[0]) * V / (33 * chrconf['GeneSize']) + lim[0]
    PromotersPath = {v: k for k, v in Individue.PromoterMap.items()}
    # print(PromotersPath)
    #print(Individue[:])
    Promoters = list(PromotersPath.keys())
    for C in Individue:
        for BP in range(len(C)):
            if C[BP] in Promoters:
                read_window = C[BP + 1: BP + 1 + GeneSize]
                read_window = [V for V in read_window if type(V) == int and V < 33]
                Value = sum(read_window)
                ParameterName = PromotersPath[C[BP]]
                Value = R(Value, stratSettings[ParameterName])
                Settings[ParameterName] = Value
    _Settings = parameterOperations.expandNestedParameters(Settings)
    return _Settings


def getToolbox(Strategy, genconf, Attributes):
    toolbox = base.Toolbox()
    creator = Creator.init(base.Fitness, {'promoterMap': None, 'Strategy': Strategy})
    # creator.create("FitnessMax", base.Fitness, weights=(1.0, 3))
    toolbox.register("mate", pachytene)
    toolbox.register("mutate", mutate)
    PromoterMap = initPromoterMap(Attributes)
    toolbox.register(
        "newind", initInd, creator.Individual, PromoterMap, genconf.chromosome
    )
    toolbox.register("population", tools.initRepeat, list, toolbox.newind)
    toolbox.register(
        "constructPhenotype", constructPhenotype, Attributes, genconf.chromosome
    )
    return toolbox


def initPromoterMap(ParameterRanges):
    PRK = list(ParameterRanges.keys())
    Promoters = [x for x in PRK]
    space = list(range(120, 240))
    random.shuffle(space)
    PromoterValues = [space.pop() for x in Promoters]
    PromoterMap = dict(zip(Promoters, PromoterValues))
    # print(ParameterRanges)
    assert (len(PRK) == len(list(PromoterMap.keys())))
    return PromoterMap


def initChromosomes(PromoterMap, chrconf):
    Promoters = getPromoterFromMap(PromoterMap)
    PromoterPerChr = round(len(Promoters) / chrconf['Density']) + 1
    _promoters = deepcopy(Promoters)
    Chromosomes = [[] for k in range(PromoterPerChr)]
    while _promoters:
        for c in range(len(Chromosomes)):
            if random.random() < 0.3:
                if _promoters:
                    promoter = _promoters.pop(random.randrange(0, len(_promoters)))
                    Chromosomes[c].append(promoter)
            for G in range(chrconf['GeneSize']):
                Chromosomes[c].append(random.randrange(0, 33))
    return Chromosomes


def initInd(Individual, PromoterMap, chrconf):
    i = Individual()
    i[:] = initChromosomes(PromoterMap, chrconf)
    i.PromoterMap = PromoterMap
    return i


def generateUID():
    Chars = string.ascii_uppercase + string.digits
    UID = ''.join(random.choices(Chars), k=6)
    return UID


def chromossomeCrossover(chr1, chr2):
    if len(chr1) != len(chr2):
        top_bottom = 1 if random.random() < 0.5 else -1
        len_diff = abs(len(chr1) - len(chr2))
    else:
        top_bottom = 1
        len_diff = 0
    offset = random.randrange(0, len_diff + 1)
    minor = chr1 if len(chr1) < len(chr2) else chr2
    major = chr2 if len(chr1) < len(chr2) else chr1
    cut_point = random.randrange(0, len(minor))
    for k in range(cut_point, len(minor)):
        Buffer = major[k + offset]
        major[k + offset] = minor[k]
        minor[k] = Buffer


def pachytene(ind1, ind2):
    if len(ind1) != len(ind2):
        return

    ind1 = deepcopy(ind1)
    ind2 = deepcopy(ind2)
    ind1[:] = sorted(ind1, key=len)
    ind2[:] = sorted(ind2, key=len)
    childChr = []
    for W in range(len(ind1)):
        chromossomeCrossover(ind1[W], ind2[W])
        childChr.append(random.choice([ind1[W], ind2[W]]))
    return ind1, ind2


def mutate(ind, mutpb=0.001, mutagg=12):
    for C in range(len(ind)):
        for BP in range(len(ind[C])):
            if BP < 100:  # case BP is common base value;
                if random.random() < mutpb:
                    ind[C][BP] += random.choice(range(-mutagg, mutagg))
            else:  # case BP is in fact a promoter;
                pass
    return ind,


def clone(Chr):  #!!review this
    cut_point = random.randrange(- len(Chr), len(Chr))
    if not cut_point:
        cut_point = 1
    if cut_point > 0:
        new_chr = chr[:cut_point]
    if cut_point < 0:
        new_chr = chr[cut_point:]
    Chr += new + Chr


================================================
FILE: promoterz/representation/deapCreator.py
================================================
#    This file is part of DEAP.
#
#    DEAP is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as
#    published by the Free Software Foundation, either version 3 of
#    the License, or (at your option) any later version.
#
#    DEAP is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#    GNU Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with DEAP. If not, see <http://www.gnu.org/licenses/>.

"""The :mod:`~deap.creator` is a meta-factory allowing to create classes that
will fulfill the needs of your evolutionary algorithms. In effect, new
classes can be built from any imaginable type, from :class:`list` to
:class:`set`, :class:`dict`, :class:`~deap.gp.PrimitiveTree` and more,
providing the possibility to implement genetic algorithms, genetic
programming, evolution strategies, particle swarm optimizers, and many more.
"""

import array
import copy
import warnings
import copyreg as copy_reg

class_replacers = {}
"""Some classes in Python's standard library as well as third party library
may be in part incompatible with the logic used in DEAP. To palliate
this problem, the method :func:`create` uses the dictionary
`class_replacers` to identify if the base type provided is problematic, and if
so  the new class inherits from the replacement class instead of the
original base class.

`class_replacers` keys are classes to be replaced and the values are the
replacing classes.
"""

try:
    import numpy
    (numpy.ndarray, numpy.array)
except ImportError:
    # Numpy is not present, skip the definition of the replacement class.
    pass
except AttributeError:
    # Numpy is present, but there is either no ndarray or array in numpy,
    # also skip the definition of the replacement class.
    pass
else:
    class _numpy_array(numpy.ndarray):
        def __deepcopy__(self, memo):
            """Overrides the deepcopy from numpy.ndarray that does not copy
            the object's attributes. This one will deepcopy the array and its
            :attr:`__dict__` attribute.
            """
            copy_ = numpy.ndarray.copy(self)
            copy_.__dict__.update(copy.deepcopy(self.__dict__, memo))
            return copy_

        @staticmethod
        def __new__(cls, iterable):
            """Creates a new instance of a numpy.ndarray from a function call.
            Adds the possibility to instanciate from an iterable."""
            return numpy.array(list(iterable)).view(cls)
            
        def __setstate__(self, state):
            self.__dict__.update(state)

        def __reduce__(self):
            return (self.__class__, (list(self),), self.__dict__)

    class_replacers[numpy.ndarray] = _numpy_array

class _array(array.array):
    @staticmethod
    def __new__(cls, seq=()):
        return super(_array, cls).__new__(cls, cls.typecode, seq)
    
    def __deepcopy__(self, memo):
        """Overrides the deepcopy from array.array that does not copy
        the object's attributes and class type.
        """
        cls = self.__class__
        copy_ = cls.__new__(cls, self)
        memo[id(self)] = copy_
        copy_.__dict__.update(copy.deepcopy(self.__dict__, memo))
        return copy_

    def __reduce__(self):
        return (self.__class__, (list(self),), self.__dict__)
class_replacers[array.array] = _array

class CreatorMeta(type):
    def __new__(meta, name, base, dct):
        return super(CreatorMeta, meta).__new__(meta, name, (base,), dct)

    def __init__(cls, name, base, dct):
        # A DeprecationWarning is raised when the object inherits from the 
        # class "object" which leave the option of passing arguments, but
        # raise a warning stating that it will eventually stop permitting
        # this option. Usually this happens when the base class does not
        # override the __init__ method from object.
        dict_inst = {}
        dict_cls = {}
        for obj_name, obj in dct.items():
            if isinstance(obj, type):
                dict_inst[obj_name] = obj
            else:
                dict_cls[obj_name] = obj
        def initType(self, *args, **kargs):
            """Replace the __init__ function of the new type, in order to
            add attributes that were defined with **kargs to the instance.
            """
            for obj_name, obj in dict_inst.items():
                setattr(self, obj_name, obj())
            if base.__init__ is not object.__init__:
                base.__init__(self, *args, **kargs)

        cls.__init__ = initType
        cls.reduce_args = (name, base, dct)
        super(CreatorMeta, cls).__init__(name, (base,), dict_cls)

    def __reduce__(cls):
        return (meta_creator, cls.reduce_args)

copy_reg.pickle(CreatorMeta, CreatorMeta.__reduce__)

def meta_creator(name, base, dct):
    class_ = CreatorMeta(name, base, dct)
    globals()[name] = class_
    return class_

def create(name, base, **kargs):
    """Creates a new class named *name* inheriting from *base* in the
    :mod:`~deap.creator` module. The new class can have attributes defined by
    the subsequent keyword arguments passed to the function create. If the
    argument is a class (without the parenthesis), the __init__ function is
    called in the initialization of an instance of the new object and the
    returned instance is added as an attribute of the class' instance.
    Otherwise, if the argument is not a class, (for example an :class:`int`),
    it is added as a "static" attribute of the class.
    
    :param name: The name of the class to create.
    :param base: A base class from which to inherit.
    :param attribute: One or more attributes to add on instanciation of this
                      class, optional.
    
    The following is used to create a class :class:`Foo` inheriting from the
    standard :class:`list` and having an attribute :attr:`bar` being an empty
    dictionary and a static attribute :attr:`spam` initialized to 1. ::
    
        create("Foo", list, bar=dict, spam=1)
        
    This above line is exactly the same as defining in the :mod:`creator`
    module something like the following. ::
    
        class Foo(list):
            spam = 1
            
            def __init__(self):
                self.bar = dict()

    The :ref:`creating-types` tutorial gives more examples of the creator
    usage.
    """

    if name in globals():
        warnings.warn("A class named '{0}' has already been created and it "
                      "will be overwritten. Consider deleting previous "
                      "creation of that class or rename it.".format(name),
                      RuntimeWarning)

    # Check if the base class has to be replaced
    if base in class_replacers:
        base = class_replacers[base]
    meta_creator(name, base, kargs)



================================================
FILE: promoterz/representation/oldschool.py
================================================
#!/bin/python
import random
import json
import os

from copy import deepcopy

from .import Creator
from deap import base
from deap import tools


from . .import parameterOperations


def constructPhenotype(stratSettings, individue):
    # THIS FUNCTION IS UGLYLY WRITTEN; USE WITH CAUTION;
    # (still works :})
    Strategy = individue.Strategy
    R = lambda V, lim: ((lim[1] - lim[0]) / 100) * V + lim[0]
    AttributeNames = sorted(list(stratSettings.keys()))
    Phenotype = {}
    for K in range(len(AttributeNames)):
        Value = R(individue[K], stratSettings[AttributeNames[K]])
        Phenotype[AttributeNames[K]] = Value
    Phenotype = parameterOperations.expandNestedParameters(Phenotype)
    return Phenotype


def createRandomVarList(IndSize):
    VAR_LIST = [random.randrange(0, 100) for x in range(IndSize)]
    return VAR_LIST


def initInd(Criterion, Attributes):
    w = Criterion()
    IndSize = len(list(Attributes.keys()))
    w[:] = createRandomVarList(IndSize)
    return w


def getToolbox(Strategy, genconf, Attributes):
    toolbox = base.Toolbox()
    creator = Creator.init(base.Fitness, {'Strategy': Strategy})
    toolbox.register("newind", initInd, creator.Individual, Attributes)
    toolbox.register("population", tools.initRepeat, list, toolbox.newind)
    toolbox.register("mate", tools.cxTwoPoint)
    toolbox.register("mutate", tools.mutUniformInt, low=10, up=10, indpb=0.2)
    toolbox.register("constructPhenotype", constructPhenotype, Attributes)
    return toolbox


================================================
FILE: promoterz/sequence/__init__.py
================================================
#!/bin/python

from .locale import standard_loop
from .world import parallel_world


================================================
FILE: promoterz/sequence/locale/standard_loop.py
================================================
#!/bin/python
from deap import tools
from copy import deepcopy
import random
from deap import algorithms

from ... import statistics
from ... import evolutionHooks
from ... import validation
from ... import supplement


def checkPopulation(population, message):
    if not (len(population)):
        print(message)


def execute(World, locale):

    # --populate if we don't have population (migrations might do it);
    if not (locale.population):
        locale.population = locale.extratools.ImmigrateRandom(
            (5, 10),
            locale.population
        )

    locale.extraStats = {}

    # --validate individuals;
    locale.population = validation.validatePopulation(
        World.tools.constructPhenotype,
        World.TargetParameters,
        locale.population
    )

    # --remove equal citizens before evaluation for efficency
    nonevaluated = [ind for ind in locale.population if not ind.fitness.valid]
    Lu = len(nonevaluated)
    print("first unevaluated: %i" % len(nonevaluated))
    remains = locale.extratools.populationPD(nonevaluated, 1.0)
    Lr = len(remains)
    print("%i individues removed due to equality" % (Lu - Lr))
    locale.population = [
        ind for ind in locale.population if ind.fitness.valid
    ] + remains

    # --load current dataset for locale;
    locale.Dataset = World.loadDatasetForLocalePosition(locale.position)

    # --evaluate individuals;
    locale.extraStats['nb_evaluated'], locale.extraStats[
        'avgTrades'
    ] = World.parallel.evaluatePopulation(
        locale
    )

    locale.extraStats['avgExposure'] = sum(
        [I.averageExposure
         for I in locale.population])/len(locale.population)

    # --send best individue to HallOfFame;
    if not locale.EPOCH % 15:
        BestSetting = tools.selBest(locale.population, 1)[0]
        locale.HallOfFame.insert(BestSetting)
    assert (sum([x.fitness.valid for x in locale.population]) == len(locale.population))

    # --compile stats;
    World.EvaluationModule.compileStats(locale)

    # --population ages
    qpop = len(locale.population)
    locale.population = locale.extratools.populationAges(
        locale.population, locale.EvolutionStatistics[locale.EPOCH]
    )
    wpop = len(locale.population)
    locale.extraStats['nbElderDies'] = qpop - wpop

    # INDIVIDUE FITNESS ATTRIBUTES FILTERS;
    # --remove very inapt citizens
    if World.conf.generation.minimumProfitFilter is not None:
        locale.extratools.filterThreshold(World.conf.generation.minimumProfitFilter,
                                          World.conf.generation._lambda)
        checkPopulation(locale.population,
                        "Population dead after profit filter.")

    # --remove individuals below tradecount
    if World.conf.generation.TradeNumberFilterRange is not None:
        locale.extratools.filterTrades(World.conf.generation.TradeNumberFilterRange,
                                       World.conf.generation._lambda)
        checkPopulation(locale.population,
                        "Population dead after trading number filter.")

    # --remove individues based on average roundtripe exposure time;
    if World.conf.generation.averageExposureLengthFilterRange is not None:
        locale.extratools.filterExposure(
            World.conf.generation.averageExposureLengthFilterRange,
            World.conf.generation._lambda
        )
        checkPopulation(locale.population,
                        "Population dead after roundtrip exposure filter.")

    if not locale.population:
        locale.population = World.tools.population(World.conf.generation.POP_SIZE)
        print("Repopulating... Aborting epoch.")

    # --show stats;
    World.EvaluationModule.showStatistics(locale)

    # --calculate new population size;
    if locale.EPOCH:
        PRoFIGA = supplement.PRoFIGA.calculatePRoFIGA(
            World.conf.generation.PRoFIGA_beta,
            locale.EPOCH,
            World.conf.generation.NBEPOCH,
            locale.EvolutionStatistics[locale.EPOCH - 1],
            locale.EvolutionStatistics[locale.EPOCH],
        )
        locale.POP_SIZE += locale.POP_SIZE * PRoFIGA

        # put population size inside thresholds;
        minps = World.conf.generation.POP_SIZE // 2
        maxps = World.conf.generation.POP_SIZE * 3
        try:
            _POP_SIZE = max(min(locale.POP_SIZE, maxps), minps)
            locale.POP_SIZE = int(round(_POP_SIZE))
        except Exception as e:
            locale.POP_SIZE = 30
            M = "POP_SIZE PROFIGA ERROR;"
            print(M)

    # --filter best inds;
    locale.population[:] = evolutionHooks.selBest(locale.population,
                                                  locale.POP_SIZE)
    checkPopulation(locale.population,
                    "Population dead after selection of score filter.")
    assert (None not in locale.population)

    # --select best individues to procreate
    LAMBDA = max(World.conf.generation._lambda,
                 locale.POP_SIZE - len(locale.population))

    TournamentSize = max(2 * LAMBDA,
                         len(locale.population))

    offspring = evolutionHooks.Tournament(locale.population,
                                          LAMBDA,
                                          TournamentSize)

    offspring = [deepcopy(x) for x in offspring]  # is deepcopy necessary?

    # --modify and integrate offspring;
    offspring = algorithms.varAnd(
        offspring, World.tools, World.conf.generation.cxpb, World.conf.generation.mutpb
    )

    locale.extratools.ageZero(offspring)
    locale.population += offspring

    # --NOW DOESN'T MATTER IF SOME INDIVIDUE LACKS FITNESS VALUES;
    assert (None not in locale.population)

    # --immigrate individual from HallOfFame;
    if random.random() < 0.2:
        locale.population = locale.extratools.ImmigrateHoF(locale.population)

    # --immigrate random number of random individues;
    if random.random() < 0.5 or not locale.population:
        locale.population = locale.extratools.ImmigrateRandom(
            (2, 7),
            locale.population
        )

    assert (None not in locale.population)


================================================
FILE: promoterz/sequence/world/parallel_world.py
================================================
#!/bin/python
import random
import itertools
import math
import time


def execute(World):

    # --APPLY MIGRATION BETWEEN LOCALES;
    if len(World.locales):
        S, D = False, False
        LocalePairs = itertools.combinations(World.locales, 2)
        for L in LocalePairs:
            distance = World.calculateDistance(L[0].position, L[1].position)
            distance_weight = distance / World.maxdistance
            if random.random() > distance_weight:
                World.migration(L[0], L[1], (1, 7))
                World.migration(L[1], L[0], (1, 7))

    # --APPLY LOCALE CREATION;
    if random.random() < World.conf.generation.localeCreationChance / 100:
        World.generateLocale()

    # --APPLY RANDOMIC LOCALE DESTRUCTION;
    if random.random() < World.conf.generation.localeExplodeChance / 100:
        chosenLocale = random.choice(World.locales)
        World.explodeLocale(chosenLocale)

    # --APPLY EXPECTED LOCALE DESTRUCTION;
    for L in range(len(World.locales)):
        if World.locales[L].EPOCH > World.conf.generation.localeExpirationAge:
            if len(World.locales) > 2:
                World.explodeLocale(World.locales[L])
                #  if two locales are destroyed @ same time, post-locale migrations
                #  will be a mess
                break

    # --APPLY LOCALE WALKS;
    for L in range(len(World.locales)):
        if random.random() < World.conf.generation.localeWalkChance / 100:
            World.localeWalk(World.locales[L])


================================================
FILE: promoterz/statistics.py
================================================
#!/bin/python

import numpy as np
from deap import tools


def getStatisticsMeter():
    stats = tools.Statistics(lambda ind: ind.fitness.values[0])
    stats.register("avg", np.mean)
    stats.register("std", np.std)
    stats.register("min", np.min)
    stats.register("max", np.max)

    return stats


================================================
FILE: promoterz/supplement/PRoFIGA.py
================================================
#!/bin/python

def calculatePRoFIGA(beta, EPOCH, NBEPOCH, oldstats, Stats):
    remainingEPOCH_NB = NBEPOCH - EPOCH

    X = beta * remainingEPOCH_NB * (Stats['max'] - oldstats['max']) / oldstats['max']
    return X


================================================
FILE: promoterz/supplement/age.py
================================================
# 1/bin/python
from deap import base


def _maturePopulation(population):
    for W in range(len(population)):
        try:
            assert (population[W].Age)
        except:
            population[W].Age = 0
        population[W].Age += 1


def _checkRetirement(individue, statistics, ageBoundary):
    # (Minetti, 2005)
    indscore = individue.fitness.values[0]
    N = (ageBoundary[1] - ageBoundary[0]) / 2
    aptitude = indscore - statistics['avg']
    if aptitude > 0:
        ABC = sum(ageBoundary) / 2
        RSB = statistics['max'] - statistics['avg']
    else:
        ABC = ageBoundary[0]
        RSB = statistics['avg'] - statistics['min']
    RSB = max(1, RSB)
    survival = ABC + (N * aptitude / RSB)
    # oldenough = individue.Age > ageBoundary[0]
    #relativeAge = (individue.Age-ageBoundary[0]) / (ageBoundary[1]-ageBoundary[0])
    retires = individue.Age - survival > ageBoundary[1]
    # print(survival)
    return retires


def _killElders(population, statistics, ageBoundary):
    for I in range(len(population)):
        if _checkRetirement(population[I], statistics, ageBoundary):
            population[I] = None
    population = [x for x in population if x]
    return population


def ageZero(population):
    for q in range(len(population)):
        population[q].Age = 0


def populationAges(ageBoundary, population, averageScore):
    _maturePopulation(population)
    population = _killElders(population, averageScore, ageBoundary)
    return population


================================================
FILE: promoterz/supplement/phenotypicDivergence.py
================================================
#!/bin/python
from deap import tools
from . .import parameterOperations
import random


def checkPhenotypicDivergence(constructPhenotype, indA, indB):
    cmp = [indA, indB]
    cmp = [constructPhenotype(x) for x in cmp]
    cmp = [parameterOperations.flattenParameters(x) for x in cmp]
    score = 0
    for w in cmp[0].keys():
        if cmp[0][w] != cmp[1][w]:
            score += 1
    return score


def populationPhenotypicDivergence(constructPhenotype, population, delpercent):
    if len(population) > 1:
        for I in range(len(population) - 1):
            for J in range(I + 1, len(population)):
                if population[I]:
                    score = checkPhenotypicDivergence(
                        constructPhenotype, population[I], population[J]
                    )
                    if not score and random.random() < delpercent:
                        population[I] = None
    population = [x for x in population if x]
    return population


================================================
FILE: promoterz/validation.py
================================================
#!/bin/python
from .parameterOperations import flattenParameters


def checkPhenotypeParameterIntegrity(TargetParameters, phenotype):
    cmp = [TargetParameters, phenotype]
    cmp = [flattenParameters(x) for x in cmp]
    # print(cmp)
    cmp = [list(x.keys()) for x in cmp]
    # print("%i ---- %i" % (len(cmp[0]), len(cmp[1])))
    for w in cmp[0]:
        if not w in cmp[1]:
            return w

    return None


def checkPhenotypeAttributeRanges(TargetParameters, phenotype, tolerance=0.3):
    cmp = [TargetParameters, phenotype]
    cmp = [flattenParameters(x) for x in cmp]
    for K in cmp[0].keys():
        high_bound = cmp[0][K][1] + (tolerance * abs(cmp[0][K][1]))
        low_bound = cmp[0][K][0] - (tolerance * abs(cmp[0][K][0]))
        higher = cmp[1][K] > high_bound
        lower = cmp[1][K] < low_bound
        if higher or lower:
            return "%f %s %f" % (low_bound, K, high_bound)

    return None


def validatePopulation(IndividualToSettings, TargetParameters, population):
    ErrMsg = "--destroying invalid citizen--\n\t({ErrType} {ErrParameter})\n"
    for p in range(len(population)):
        phenotype = IndividualToSettings(population[p])
        Err = checkPhenotypeParameterIntegrity(TargetParameters, phenotype)
        if Err:
            print(ErrMsg.format(ErrType='missing parameter', ErrParameter=Err))
            population[p] = None
            continue

        Err = checkPhenotypeAttributeRanges(TargetParameters, phenotype)
        if Err:
            print(ErrMsg.format(ErrType=' invalid values on', ErrParameter=Err))
            population[p] = None
        if not population[p]:
            print(phenotype)
            pass
    population = [x for x in population if x]
    return population


================================================
FILE: promoterz/webServer/__init__.py
================================================
#!/bin/python

from .import core


================================================
FILE: promoterz/webServer/core.py
================================================
#!/bin/python
import os
import re
import datetime

import flask
import dash

from dash.dependencies import Input, Output

import dash_core_components as dcc
import dash_html_components as html

from flask_caching import Cache
from evaluation.gekko.statistics import epochStatisticsNames, periodicStatisticsNames

from . import graphs
from . import layout

import functools
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)


def build_server(webpageTitle):
    # Setup the app
    server = flask.Flask(__name__)
    app = dash.Dash(__name__, server=server, csrf_protect=False)

    app.scripts.config.serve_locally = False
    app.css.config.serve_locally = False

    app.webpageTitle = webpageTitle

    timeout = 60 * 60  # 1 hour

    app.startTime = datetime.datetime.now()

    # Graph Update function bindings;
    app.updateLocaleGraph = graphs.updateLocaleGraph
    app.updateWorldGraph = graphs.updateWorldGraph
    app.updateEvalBreakGraph = graphs.updateEvalbreakGraph

    # Graphics initialization and input points against World;
    # why is this placeholder required? ;(
    app.WorldGraph = dcc.Graph(id='WorldGraph', figure={})
    app.LocaleGraphs = []
    app.EvalBreakGraph = []

    app.resultParameters = []
    app.epochInfo = ""
    app.layout = functools.partial(layout.getLayout, app)

    app.config['suppress_callback_exceptions'] = False

    # event triggers
    onRefreshClick = Input('refresh-button', 'n_clicks')

    """
    # update graph methods
    @app.callback(Output('last-refresh', 'children'),
                  [Input('refresh-button', 'n_clicks')])
    def display_time(w):
        print("Refreshing graphical interface graphics.")
        return str(datetime.datetime.now())

    @app.callback(Output('WorldGraph', 'children'),
                  [Input('refresh-button', 'n_clicks')])
    def updateGGraphs(w):
        return [app.WorldGraph]

    @app.callback(Output('LocaleGraphs', 'children'),
                  [Input('refresh-button', 'n_clicks')])
    def updateLGraphs(w):
        return [app.GraphicList]
    """

    # SELECT PAGE;
    @app.callback(dash.dependencies.Output('page-content', 'children'),
                  [dash.dependencies.Input('url', 'pathname')])
    def display_page(pathname):
        if re.findall("evalbreak", str(pathname)):
            return layout.getEvalbreak(app)
        if re.findall("results", str(pathname)):
            return layout.getResults(app)
        else:
            return layout.getCommon(app)

    @server.route('/static/<path:path>')
    def send_css(path):
        return flask.send_from_directory(os.path.dirname(__file__), path)

    # load external css
    currentDirectory = os.path.dirname(os.path.abspath(__file__))
    externalCssListPath = os.path.join(currentDirectory,
                                       "external_css_list.txt")

    with open(externalCssListPath) as cssListFile:
        external_css = cssListFile.read().split("\n")
        external_css = list(filter(None, external_css))

    for css in external_css:
        app.css.append_css({"external_url": css})

    # launch DASH APP
    return app, server


================================================
FILE: promoterz/webServer/external_css_list.txt
================================================
https://fonts.googleapis.com/css?family=Overpass:400,400i,700,700i
https://cdn.jsdelivr.net/gh/plotly/dash-app-stylesheets@c6a126a684eaaa94a708d41d6ceb32b28ac78583/dash-technical-charting.css


================================================
FILE: promoterz/webServer/graphs.py
================================================
#!/bin/python

import dash_core_components as dcc

from evaluation.gekko.statistics import epochStatisticsNames, periodicStatisticsNames


def updateWorldGraph(app, WORLD):
    environmentData = [
        {
        }
    ]
    populationGroupData = [
        {
            'x': [locale.position[0]],
            'y': [locale.position[1]],
            'type': 'scatter',
            'name': locale.name,
            'showscale': False,
            'mode': 'markers',
            'marker': {
                'symbol': 'square'
            }

        } for locale in WORLD.locales
    ]

    fig = {
        'data': populationGroupData,
        'layout': {
            'title': "World Topology: 2D MAP"
        }
    }


    G = dcc.Graph(id="WorldGraph", figure=fig)
    #app.layout.get("WorldGraphContainer").children = [G]
    app.WorldGraph = G
    return G


def updateLocaleGraph(app, LOCALE):

    GraphName = LOCALE.name
    print('Loading %s' % GraphName)
    Statistics = LOCALE.EvolutionStatistics
    ID = [s for s in GraphName if s.isdigit()]
    annotations = []

    oldLocaleGraph = None
    for lidx, localeGraph in enumerate(app.LocaleGraphs):
        if localeGraph.id == LOCALE.name:
            oldLocaleGraph = lidx
            break

    statisticsNames = {}
    statisticsNames.update(epochStatisticsNames)
    # statisticsNames.update(periodicStatisticsNames)

    annotationFontDescription = {
        'family': 'Arial',
        'size': 12,
        'color': 'rgb(37,37,37)'
    }

    """
    for Statistic in Statistics:
        if 'dateRange' in Statistic.keys():
            if Statistic['dateRange']:
                for R, dateRange in enumerate(Statistic['dateRange']):
                    if dateRange is not None:
                        annotations.append(
                            {
                                'xref': 'axis',
                                'yref': 'paper',
                                'xanchor': 'left',
                                'yanchor': 'bottom',
                                'font': annotationFontDescription,
                                'x': R,
                                'y': 1 if not len(annotations) %
                                2 else 0.93,  # avoid label overlap;
                                'text': dateRange,
                            }
                        )
    """

    colorSequence = [
        (188, 189, 34),
        (100, 11, 182),
        (186, 3, 34),
        (45, 111, 45),
        (66, 128, 66),
        (128, 66, 66),
    ]
    statNames = [
        'avg', 'std', 'min',
        'max',
        #'evaluationScore',
        #'evaluationScoreOnSecondary'
    ]

    DATA = [
            {
                'x': [Statistic['id'] for Statistic in Statistics],
                'y': [Statistic[statNames[S]] for Statistic in Statistics],
                'type': 'line',
                'name': statisticsNames[statNames[S]],
                'line': {'color': 'rgb%s' % str(colorSequence[S])},
            }
            for S in range(len(statNames))
        ]

    fig = {
        'data': DATA,
        'layout': {
            'title': 'Evolution at %s' % GraphName,
            'annotations': annotations
        },
    }

    G = dcc.Graph(figure=fig, id=LOCALE.name)
    if oldLocaleGraph is not None:
        app.LocaleGraphs[oldLocaleGraph] = G
    else:
        app.LocaleGraphs.append(G)

    return G


def updateEvalbreakGraph(app, EvaluationSummary):

    K = ["evaluation", "secondary"]
    GES = dict([(k, []) for k in K])
    for E in EvaluationSummary:
        for k in K:
            if k in E.keys():
                GES[k].append(E[k])
            else:
                GES[k].append(None)

    DATA = [
        {
            'x': list(range(len(GES[KEY]))),
            'y': GES[KEY],
            'type': 'line',
            'name': KEY.upper()
        } for KEY in GES.keys()
    ]

    figure = {
        'data': DATA,
        'layout': {
            'title': "Evaluation Breaks"
        }
    }

    G = dcc.Graph(figure=figure, id="EvaluationBreaksGraph")
    app.EvalBreakGraph = G
    return G


================================================
FILE: promoterz/webServer/layout.py
================================================
#!/bin/python

import dash_core_components as dcc
import dash_html_components as html
import datetime


allStyle = {
            'width': '1100',
            'margin-left': 'auto',
            'margin-right': 'auto',
            'font-family': 'overpass',
            'background-color': '#F3F3F3'
        }


def getLayout(app):
    layout = html.Div([
        dcc.Location(id='url', refresh=False),
        getHeader(app),
        html.Div(id='page-content')
    ])
    return layout


def getHeader(app):
    # this is a mess;
    inlineBlock = {"display": "inline-block"}
    headerWidgets = [
        html.Button("Refresh", id='refresh-button'),
        html.Div(
            [
                html.Div("Last refresh @ ", style=inlineBlock.update({"float": "left"})),
                html.Div(datetime.datetime.now(),
                         id='last-refresh', className="showTime",
                         style=inlineBlock.update({"float": "left"})),

                html.Div("%s Start time" % app.startTime,
                         id='start-time', className="showTime",
                         style=inlineBlock.update({"float": "right"})),
                html.Br(),
                html.Center([
                    html.Div(app.epochInfo, id="current-epoch")
                    ])
            ], className="showTime")
    ]

    pageMenu = [
        html.A(html.Button("Evolution Statistics"), href="/"),
        html.A(html.Button("Evaluation Breaks"), href="/evalbreak"),
        html.A(html.Button("View Results"), href="/results")
        # html.Button("View Settings", className="unimplemented"),
        # html.Button("Inspect Population", className="unimplemented")
    ]



    # html.Link(rel='stylesheet', href='/static/promoterz_style.css'),
    header = html.Div(
        [
            html.H2(
                app.webpageTitle,
                style={'padding-top': '20', 'text-align': 'center'},
            ),
            html.Div(headerWidgets),
            html.Div(pageMenu),
        ],
        style=allStyle)

    return header


def getCommon(app):
    return html.Div([
        html.Div(children=app.WorldGraph, id='WorldGraphContainer'),
        html.Div(children=app.LocaleGraphs, id='LocaleGraphsContainer')
    ], style=allStyle)


def getEvalbreak(app):
    return html.Div([
        html.Div(children=app.EvalBreakGraph, id='EvalBreakContainer')
    ], style=allStyle)


def getResults(app):
    return [html.Textarea(str(r[0]) + '\n' + str(r[1]), style={'width': '525', 'height': '550'}) for r in app.resultParameters]


================================================
FILE: promoterz/webServer/promoterz_style.css
================================================
.unimplemented {
    background-color: #666;
} 

.showTime {
    display: inline-block;
}


================================================
FILE: promoterz/world.py
================================================
#!/bin/python
import random

import time
import math

from . import locale


class World():
    def __init__(
            self,
            GlobalTools=None,
            populationLoops=None,
            worldLoops=None,
            conf=None,
            TargetParameters=None,
            EnvironmentParameters=None,
            onInitLocale=None,
            web=None,
    ):
        self.tools = GlobalTools

        # main components
        self.populationLoops = populationLoops
        self.worldLoops = worldLoops

        # genetic algorithm status
        self.EPOCH = 0
        self.locales = []
        self.totalEvaluations = 0

        # genetic algorithm attributes
        self.size = [500, 500]
        self.maxdistance = self.calculateDistance([0, 0], self.size)
        self.TargetParameters = TargetParameters

        self.conf = conf
        # Temporary assignment of configs

        self.localeID = 1
        self.EnvironmentParameters = EnvironmentParameters
        self.onInitLocale = onInitLocale
        self.web = web

    def generateLocale(self):
        name = 'Locale%i' % (self.localeID)
        self.localeID += 1
        position = [random.randrange(0, self.size[x]) for x in range(2)]

        L = locale.Locale(self,
                          name,
                          position,
                          random.choice(self.populationLoops)
        )

        self.locales.append(L)

    def migration(self, source, target, number_range):
        number = random.randrange(*number_range)
        for W in range(number):
            if len(source.population):
                index = random.randrange(0, len(source.population))
                individual = source.population.pop(index)
                del individual.fitness.values
                target.population.append(individual)

    def explodeLocale(self, explLocale):
        if len(self.locales) < 2:
            return

        totaldistance = 0
        for T in self.locales:
            if explLocale == T:
                T.tempdist = 0
                continue

            distance = self.calculateDistance(
                explLocale.position, T.position)
            T.tempdist = distance
            totaldistance += distance
        for T in self.locales:
            fugitiveNumber = T.tempdist / totaldistance *\
                len(explLocale.population)

            T.fugitivenumber = int(round(fugitiveNumber))

        for T in self.locales:
            self.migration(explLocale, T,
                           (T.fugitivenumber, T.fugitivenumber + 1))
            del T.tempdist
            del T.fugitivenumber

        self.locales = [x for x in self.locales if x != locale]

    def runEpoch(self):
        epochHeader = "EPOCH %i/%i" % (
            self.EPOCH,
            self.conf.generation.NBEPOCH
        )

        print("\t====== %s ======" % epochHeader)
        epochStartTime = time.time()

        if self.web:
            self.epochInfo = epochHeader
            self.web.updateWorldGraph(app=self.web, WORLD=self)

        for LOCALE in self.locales:
            LOCALE.run()
            if self.web:
                self.web.updateLocaleGraph(app=self.web, LOCALE=LOCALE)

        self.worldLoops[0](self)

        self.EPOCH += 1
        epochRunTime = time.time() - epochStartTime
        print("Epoch runs in %.2f seconds;" % epochRunTime)
        if not self.EPOCH % 10:
            print("Backend power %s" % self.parallel.lasttimesperind)
        print("")

    @staticmethod
    def calculateDistance(point1, point2):
        x = abs(point1[0] - point2[0])
        y = abs(point1[1] - point2[1])
        D = math.sqrt(x ** 2 + y ** 2)
        return D

    def seedEnvironment(self):
        # round to nearest square number
        self.sectorSeedRoot = round(math.sqrt(self.conf.generation.worldSeedSize))

        self.environmentSectors = []
        for i in range(self.sectorSeedRoot):
            row = []
            for j in range(self.sectorSeedRoot):
                ENV = self.onInitLocale(self)
                row.append(ENV)
            self.environmentSectors.append(row)

    def loadDatasetForLocalePosition(self, position):
        pos = [math.floor(P / self.size[p] * self.sectorSeedRoot)
               for p, P in enumerate(position)]

        return self.environmentSectors[pos[0]][pos[1]]

    def localeWalk(self, locale):
        ammount = self.conf.generation.localeWalkDistance

        variation = [random.randrange(-ammount, ammount)
                     for i in range(2)]

        for i in range(2):
            locale.position[i] += variation[i]

            # put it inside boundaries,
            # make world appear rounded like our planet :3;

            # fix too low values
            while locale.position[i] < 0:
                locale.position[i] += self.size[i]

            # fix too high values
            locale.position[i] = locale.position[i] % self.size[i]


================================================
FILE: requirements.txt
================================================
ccxt==1.13.139
pandas_datareader==0.5.0
numpy==1.16.2
tulipy==0.2
pandas==0.18.1
deap==1.2.2
scipy==0.19.0
pytoml==0.1.16
Js2Py==0.59
Flask_Caching==1.4.0
Quandl==3.4.0
dash==0.39.0
dash-daq==0.1.0
Flask==1.0.2
requests>=2.20.0
bayesian_optimization==0.6.0
zipline==1.2.0
arch==4.3.1
names==0.3.0
matplotlib==2.2.2
python_dateutil==2.7.3
pytz==2018.5
scikit_learn==0.19.2
waitress


================================================
FILE: settings/_Global.toml
================================================
gekkoPath = '$HOME/gekko'
configFilename = 'example-config.js'
log_name = 'evolution_gen.csv'

# Hosts list of remote machines running gekko, to distribute evaluation load;
# option values: path to HOSTS file list OR False;
RemoteAWS = '../AmazonSetup/hosts'

# Your gekko local URL - CHECK THIS!
# gekko:3000 stands for the default url at docker-compose scheme of things.
GekkoURLs = ['http://localhost:3000', 'http://gekko:3000']
showFailedStrategies = true



================================================
FILE: settings/_backtest.toml
================================================
# show gekko verbose (strat info) - gekko must start with -d flag;
gekkoDebug = 0
# time window size on days of candlesticks for each evaluation
deltaDays = 90
# candle size for gekko backtest in minutes
candleSize = 10
# mode of profit interpretation = v1, v2 or v3.
# please check the first functions at evaluation.gekko.backtest
# to understand what is this. has big impact on evolutionary agenda.
interpreteBacktestProfit = 'v3'
# Number of candlestick data loaded simultaneously in each locale;
# slower EPOCHS theoretical better evolution;
# seems broken. values other than 1 makes evolution worse.
ParallelCandlestickDataset = 1
# number of parallel backtests running on gekko;
ParallelBacktests = 6




================================================
FILE: settings/_bayesian.toml
================================================


================================================
FILE: settings/_binance.toml
================================================
credentialsFilePath = ""
strategyRunTimePeriodHours = 12
strategySelectorSigma = 10
# following option points to binance asset/currency .json file located at
# 'exchanges' folder of gekko. selecting it up is optional.
binanceAssetCurrencyTargetFilePath = ""


================================================
FILE: settings/_dataset.toml
================================================
# span in days from the end of dataset to the beggining. Or zero.
# (to restrain length);
dataset_span = 0
# span for evaluation dataset. same scheme.
eval_dataset_span = 0


# -- Gekko Dataset Settings
# in order to enable dataset selection, turn off autoselect entry;
[dataset_source]
autoselect = true
exchange = 'kraken'
currency = 'USD'
asset = 'LTC'

[dataset_source2]
autoselect = true
exchange = 'kraken'
currency = 'USD'
asset = 'LTC'

[eval_dataset_source]
autoselect = true
exchange = 'kraken'
currency = 'USD'
asset = 'LTC'





================================================
FILE: settings/_evalbreak.toml
================================================
# number of individues selected by score on each evaluation break for each locale;
NBBESTINDS = 1
# number of individues randomly selected on each evaluation break for each locale;
NBADDITIONALINDS = 4

# show current best settings on every X epochs. (or False)
evaluateSettingsPeriodically = 50

# number of evaluations on evaluation break. for each selected individue on locales;
proofSize = 12




================================================
FILE: settings/_generation.toml
================================================

# Verbose single evaluation results;
showIndividualEvaluationInfo = false

# if parameter is set to value rather than tuple limits at settings make the value
# a tuple based on chosen spread value (percents); value = 10 --spread=50-->  value = (515)
parameter_spread  = 60

# Initial population size per locale
POP_SIZE = 50

# number of epochs to run
NBEPOCH = 3000

# number of locales on parallel GA;
NBLOCALE = 3

# -- Genetic Algorithm Parameters
cxpb = 0.8 # Probabilty of crossover 
mutpb = 0.2# Probability of mutation;
_lambda = 14# size of offspring generated per epoch;

# weight of PRoFIGA calculations on variability of population size
PRoFIGA_beta = 0.005
ageBoundaries = [9, 19] # minimum age to die age when everyone dies (on EPOCHS)

# after this age in epoches locale surely explodes i.e. ends.
localeExpirationAge = 100

# chance on each epoch of a locale to finish [in percentage];
localeExplodeChance = 2

# chance on each epoch of a locale creation [in percentage];
localeCreationChance = 2

# chance on each epoch of a locale to change position [in percentage];
localeWalkChance = 40

# max distance a locale can walk across world map on each epoch;
localeWalkDistance = 5

# number of different candle date ranges to seed world;
# no area overlap, no empty spaces.
# this rounds to the nearest square number.
worldSeedSize = 40

# filter individuals for minimum profit (or set to None)
minimumProfitFilter = -15

# filter individuals for minimum trade count; [has heavy impact] (or set to None)
TradeNumberFilterRange = [6, 300]

# filter individuals with roundtripe duration outside this range of values in hours (or set to None)
averageExposureLengthFilterRange = [0, 300]


# until another time range in dataset is selected;

# chromosome settings are for -gc mode which uses another GA internal representation mode
# for parameter values of each individue;
# check promoterz/representation/chromosome.py to see how it works.
# both parameters interact with crossover probability AKA cxpb;
# practical effects on evolution are really uknown;

[chromosome]
# length of the representation for each parameter. largers sizes should mantain
# evolutionary dynamics for parameters with proportional larger ranges;
GeneSize = 3
# number of parameters represented by each cromosome;
# this should mantain evolutionary dynamics for strategies with proportional larger
# parameter counts;
Density = 2


# weights to score each individual self explanatory;
[weights]
profit = 1.0
sharpe = 0.1







================================================
FILE: stratego/README.md
================================================
### Usage

This is a submodule of japonicus. This takes care of on-the-fly strategy creation and management.
Its on a very beta stage, like the rest of this GA implementation.

### TODO:

The method is to just sum indicators, I.E to buy, all indicators should be above threshold.
That can work, but more complex interactions between indicators should be implemented.

### Disclaimer:

stratego? japonicus? promoterz? from which depth of hell do those names come? hehehe


================================================
FILE: stratego/__init__.py
================================================
# 1/bin/python
from .import gekko_strategy


================================================
FILE: stratego/gekko_strategy.py
================================================
#!/bin/python
import os
import random
import hashlib
import re
from collections import OrderedDict

# from . import Settings
from .indicator_properties import *

# gekkoStratFolder = Settings('').Global['gekkoDir']+'/strategies/'
simplifyIndicators = lambda name: "var {I} = this.indicators.{i};".format(
    i=name.lower(), I=name.upper()
)
addIndicatorText = lambda name: "this.addIndicator('{i}', '{I}', this.settings.{I}{A});".format(
    i=name.lower(), I=name.upper(), A=IndicatorProperties[name]['input']
)
onlyLetters = lambda message: re.sub(r"[^A-Za-z]+", '', message)


class StrategyFileManager():

    def __init__(self, gekkoPath, indicatorSettings):
        self.gekkoStratFolder = gekkoPath + '/strategies/japonicus/'
        self.gekkoIndicatorFolder = gekkoPath + '/strategies/indicators/'
        if not os.path.isdir(self.gekkoStratFolder):
            os.mkdir(self.gekkoStratFolder)
        AllowedIndicators = list(IndicatorProperties.keys())
        AllowedIndicators = [
            ind for ind in AllowedIndicators if indicatorSettings[ind]['active']
        ]
        baseContent = open('stratego/skeleton/ontrend.js').read()
        self.baseMD5 = hashlib.md5(baseContent.encode('utf-8')).hexdigest()
        self.sessionCreatedFiles = []
        self.skeletonHeader = [
            l for l in baseContent.split('\n') if '//JAPONICUS' in l
        ][
            0
        ]
        self.skeletonHeader = self.interpreteSkeletonHeader(self.skeletonHeader)
        for I in range(len(AllowedIndicators)):
            if not os.path.isfile(
                "%s%s.js" % (self.gekkoIndicatorFolder, AllowedIndicators[I])
            ):
                print("Indicator %s doesn't exist!" % AllowedIndicators[I])
                AllowedIndicators[I] = None
        self.AllowedIndicators = [x for x in AllowedIndicators if x]
        if not self.AllowedIndicators:
            exit("No usable indicators detected.")

    def selectIndicator(self, chosenIndicators, phenotype, Type):
        indicatorsOnPhenotype = [
            ind for ind in phenotype.keys() if ind in IndicatorProperties.keys()
        ]
        allOfType = [
            ind
            for ind in indicatorsOnPhenotype
            if IndicatorProperties[ind]['group'] == Type
        ]
        Indicators = sorted(
            allOfType, key= lambda ind: phenotype[ind]['active'], reverse=True
        )
        chosenIndicatorNames = [
            chosenIndicators[name] for name in chosenIndicators.keys()
        ]
        for Ind in Indicators:
            if Ind not in chosenIndicatorNames:
                return Ind

        raise RuntimeError("not enough indicators for strategy %s;" % Indicators)

    def checkStrategy(self, phenotype):
        AllIndicators = self.AllowedIndicators
        Indicators = {}
        for indicatorInternalName in self.skeletonHeader.keys():
            selectedIndicatorType = self.skeletonHeader[indicatorInternalName]
            selectedIndicator = self.selectIndicator(
                Indicators, phenotype, selectedIndicatorType
            )
            Indicators.update({indicatorInternalName: selectedIndicator})

        def sortIndicators(ind):
            if ind in phenotype.keys():
                return phenotype[ind]['active']

            else:
                return 0

        FallbackIndicators = [x for x in AllIndicators if x in phenotype.keys()]
        if not Indicators:
            Indicators = sorted(FallbackIndicators, key=sortIndicators, reverse=True)[
                0:2
            ]
        if not Indicators:
            exit("NO INDICATORS")
        IndicatorNames = [Indicators[slot] for slot in Indicators.keys()]
        StrategyFileName = 'j' + self.baseMD5[-4:] + ''.join(IndicatorNames)
        stratpath = self.gekkoStratFolder + StrategyFileName + '.js'
        if not os.path.isfile(stratpath):
            print(self.sessionCreatedFiles)
            self.createStrategyFile(Indicators, stratpath)
        return 'japonicus/' + StrategyFileName

    def interpreteSkeletonHeader(self, header):
        Header = OrderedDict()
        header = header.replace('//JAPONICUS:', '')
        for segment in header.split(','):
            if '|' in segment:
                segment = segment.strip(' ').split('|')
                print(segment)
                Header[segment[0]] = onlyLetters(segment[1].lower())
        return Header

    def createStrategyFile(self, Indicators, stratpath):
        BASE = open("stratego/skeleton/ontrend.js").read()
        for Indicator in Indicators.keys():
            BASE = BASE.replace(Indicator, Indicators[Indicator])
        FILE = open(stratpath, 'w')
        FILE.write(BASE)
        print("Creating strategy %s file." % stratpath)
        self.sessionCreatedFiles.append(stratpath)
        FILE.close()

    def _createStrategyFile(self, Indicators, stratpath):
        BASE = open("stratego/skeleton/dumbsum.js").read()
        InitIndicators = [addIndicatorText(ind) for ind in Indicators]
        BASE = BASE.replace("//ADD_INDICATORS;", ('\n'.join(InitIndicators)))
        SimplifyIndicators = [simplifyIndicators(ind) for ind in Indicators]
        BASE = BASE.replace("//SIMPLIFY_INDICATORS;", ('\n'.join(SimplifyIndicators)))
        BuyConditions = []
        SellConditions = []
        for ind in Indicators:
            Bc = "%s.%s %s" % (
                ind,
                IndicatorProperties[ind]['attrname'],
                IndicatorProperties[ind]['result'][0].format(i=ind),
            )
            Sc = "%s.%s %s" % (
                ind,
                IndicatorProperties[ind]['attrname'],
                IndicatorProperties[ind]['result'][1].format(i=ind),
            )
            BuyConditions.append(Bc)
            SellConditions.append(Sc)
        BASE = BASE.replace(
            "//BUYCONDITIONS;", "var BuyConditions = [%s];" % ', '.join(BuyConditions)
        )
        BASE = BASE.replace(
            "//SELLCONDITIONS;",
            "var SellConditions = [%s];" % ', '.join(SellConditions),
        )
        FILE = open(stratpath, 'w')
        FILE.write(BASE)
        print("Creating strategy %s file." % stratpath)
        self.sessionCreatedFiles.append(stratpath)
        FILE.close()


================================================
FILE: stratego/indicator_properties.py
================================================
#!/bin/python
stdResult = ["> this.settings.{i}.thresholds.up", "< this.settings.{i}.thresholds.down"]
againstPrice = ["> price", "< price"]
Reverse = lambda x: [x[1], x[0]]
IndicatorProperties = {
    "ADX": {
        "input": '', "attrname": "result", "result": stdResult, "group": "momentum"
    },
    "ATR": {
        "input": '', "attrname": "result", "result": stdResult, "group": "volatility"
    },
    "PPO": {
        "input": '', "attrname": "PPOhist", "result": stdResult, "group": "momentum"
    },
    "DEMA": {"attrname": "result", "result": stdResult, "input": '', "group": "trend"},
    "RSI": {
        "result": Reverse(stdResult),
        "input": '',
        "attrname": "result",
        "group": "momentum",
    },
    "TSI": {
        "input": '', "result": stdResult, "attrname": "result", "group": "momentum"
    },
    "LRC": {
        "result": againstPrice,
        "attrname": "result",
        "input": '.depth',
        "group": "trend",
    },
    "SMMA": {
        "input": '', "attrname": 'result', "result": stdResult, "group": "overlap"
    },
    "CCI": {
        "input": '', "result": stdResult, "attrname": 'result', "group": "momentum"
    },
}


================================================
FILE: stratego/skeleton/dumbsum.js
================================================
// helpers
var _ = require('lodash');
var log = require('../../core/log.js');

// let's create our own method
var method = {};

method.init = function() {

    this.age = 0;

    this.currentTrend;
    this.requiredHistory = 16;
    this.persistence=0;
    //ADD_INDICATORS;
    this.addindicator('inda', '..INDA..', this.settings['..INDA..'])
}

// what happens on every new candle?
method.update = function(candle) {

}


method.log = function() {

}



method.validation = function(ConditionList)
    {
       var validNB = ConditionList.filter(function(s) { return s; }).length;
       return validNB/ ConditionList.length; 
    }

method.checkPersistence = function(candidateAdvice)
{
    if (this.persistence >= this.settings.persistence)
        this.advice(candidateAdvice);
    else
        this.advice();

}

method.check = function(candle) {

    var price = candle.close;


    //SIMPLIFY_INDICATORS;

    //BUYCONDITIONS;
    //SELLCONDITIONS;
 
    this.age++;
 

    if (this.validation(BuyConditions) > 0.6)
    {

        if(this.currentTrend !== 'up') {
            this.currentTrend = 'up';
            this.advice();
            this.persistence=0;
        } else{
            this.persistence++;
            this.checkPersistence('long');

        }
    }
    else if (this.validation(SellConditions) > 0.6)
    {


        if (this.currentTrend !== 'down') {
            this.currentTrend = 'down';
            this.advice();
            this.persistence=0;
        } else{
            this.persistence++;
            this.checkPersistence('short');
        }


    } else {

        this.advice();
    }


}

module.exports = method;


================================================
FILE: stratego/skeleton/ontrend.js
================================================
/*
  skeleton adapted from former strategy:

	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
	-
	12 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 ADX';
		this.requiredHistory = 10//config.tradingAdvisor.historySize;
		this.resetTrend();
		
		// debug? set to flase to disable all logging/messages/stats (improves performance)
		this.debug = true;
		
		// performance
		//config.backtest.batchSize = 1000; // increase performance
		//config.silent = true;
		//config.debug = false;

      //JAPONICUS:BULLMOM|MOMENTUM,BEARMOM|MOMENTUM,SECMOM|MOMENTUM;

		// SMA
		this.addIndicator('maSlow', 'SMA', this.settings.SMA_long );
		this.addIndicator('maFast', 'SMA', this.settings.SMA_short );
		
		// RSI
	  this.addIndicator('BULL_momentum', 'BULLMOM', this.settings['BULLMOM'] );
		this.addIndicator('BEAR_momentum', 'BEARMOM', this.settings['BEARMOM'] );
		
		// ADX
		this.addIndicator('secondary_momentum', 'SECMOM', this.settings['SECMOM'] )
		
		
		// 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 }
			};
		}
		
	}, // init()
	
	
	/* RESET TREND */
	resetTrend: function()
	{
		var trend = {
			duration: 0,
			direction: 'none',
			longPos: false,
		};
	
		this.trend = trend;
	},
	
	

	
	
	/* CHECK */
	check: function()
	{
		// get all indicators
		let ind = this.indicators,
			maSlow = ind.maSlow.result,
			maFast = ind.maFast.result,
			sec = this.indicators.secondary_momentum.result;
		
		
			
		// BEAR TREND
		if( maFast < maSlow )
		{
			var momentum = ind.BEAR_momentum.result;
			let momentum_hi = this.settings['BEARMOM'].thresholds.up,
				momentum_low = this.settings['BEARMOM'].thresholds.down;
			
			// ADX trend strength?
			if( sec > this.settings['SECMOM'].thresholds.up ) momentum_hi = momentum_hi + 15;
			else if( sec < this.settings['SECMOM'].thresholds.down ) momentum_low = momentum_low -5;
				
			if( momentum > momentum_hi ) this.short();
			else if( momentum < momentum_low ) this.long();
			

		}

		// BULL TREND
		else
		{
			var momentum = ind.BULL_momentum.result;
			let momentum_hi = this.settings['BULLMOM'].thresholds.up,
				momentum_low = this.settings['BULLMOM'].thresholds.down;

			// ADX trend strength?
			if( sec > this.settings['SECMOM'].thresholds.up ) momentum_hi = momentum_hi + 5;
			else if( sec < this.settings['SECMOM'].thresholds.down ) momentum_low = momentum_low -5;

			if( momentum > momentum_hi ) this.short();
			  else if( momentum < momentum_low )  this.long();
			
		}
		
		// add adx low/high if debug

	
	}, // 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: strategy_parameters/BBRSI.toml
================================================
interval = 14

[thresholds]
low = 40
high = 40
persistence = 9

[bbands]
TimePeriod = 20
NbDevUp = 0.7
NbDevDn = 0.7

================================================
FILE: strategy_parameters/DUAL_RSI_BULL_BEAR.toml
================================================
[RBB1]
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 = 60
BEAR_RSI_low = 20
#ADX   
ADX = 3
ADX_high = 70
ADX_low = 50

[RBB2]
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 = 60
BEAR_RSI_low = 20
#ADX   
ADX = 3
ADX_high = 70
ADX_low = 50


================================================
FILE: strategy_parameters/HL_TS.toml
================================================
# Minimum volume needed to enter a trade
Min24hUSDVolume = 500000
RollingVolumeHours = 24
CurrencyPrice = 9000
CandleSize = 5

# Do not enter in bearish trend
# if Med>Slow (bullish) 
# else if Fast>Med (slightly bullish in bearish trend)
SMA_Fast = 50
SMA_Medium = 200
SMA_Slow = 500

DarvasPeriodSize = 24
NoTradeResetPeriod = 3

StopLossPercent = -5
MaxLongPositionHours = 12

[psar]
optInStart = 0.0
optInAcceleration = 0.25
optInMaximum = 0.5


================================================
FILE: strategy_parameters/NEO.toml
================================================
# Source: https://raw.githubusercontent.com/gcobs0834/gekko/develop/config/strategies/NEO.toml
# SMA Trends
SMA_long = 150
SMA_short = 40

# BULL
BULL_RSI = 10
BULL_RSI_high = 80
BULL_RSI_low = 50

# IDLE
IDLE_RSI = 12
IDLE_RSI_high = 65
IDLE_RSI_low = 39

# BEAR
BEAR_RSI = 15
BEAR_RSI_high = 50
BEAR_RSI_low = 25

# ROC
ROC = 6
ROC_lvl = 0

# BULL/BEAR is defined by the longer SMA trends
# if SHORT over LONG = BULL
# if SHORT under LONG = BEAR

# ROC is the LENGHT (averaging)
# Leave ROC_lvl at 0 otherwise Results are negative




================================================
FILE: strategy_parameters/NEObigjap.toml
================================================
# SETTINGS FOUND FOR NEO STRAT AT EPOCH 15.000;
# INTERNAL BACKTESTS RETURNED GREAT SCORE;
BEAR_RSI_low = 23.106060606060606
IDLE_RSI_high = 59.68181818181818
BEAR_RSI = 11.863636363636363
BULL_RSI_low = 47.121212121212125
SMA_short = 36.0
IDLE_RSI = 11.527272727272727
ROC = 4.781818181818182
IDLE_RSI_low = 34.154545454545456
BULL_RSI_high = 84.12121212121212
ROC_lvl = 0.0
BULL_RSI = 9.121212121212121
BEAR_RSI_high = 42.878787878787875
SMA_long = 145.0



================================================
FILE: strategy_parameters/PPO.toml
================================================
short = 12
long = 26
signal = 9

[thresholds]
down = -0.025
up = 0.025
persistence = 2

================================================
FILE: strategy_parameters/RBB_ADX2_BB.toml
================================================
[ADX]
adx = 3.0
high = 50

[BBands]
NbDevDn = 2.0
NbDevUp = 2.0
TimePeriod = 20.0

[BBtrend]
bearPersistence = 16
bullPersistence = 11
lowerThreshold = 50
upperThreshold = 86

[BEAR]
high = 60.0
low = 29.4
mod_high = 1.5
mod_low = -1.5
rsi = 9.2

[BULL]
high = 90
low = 37
mod_high = 6
mod_low = -13.5
rsi = 13.2

[SMA]
long = 1000.0
short = 50.0

================================================
FILE: strategy_parameters/RSI_BULL_BEAR.toml
================================================
SMA_long = [800, 1000]
SMA_short = 50

BULL_RSI = 10
BULL_RSI_high = 80
BULL_RSI_low = 60
        
BEAR_RSI = 15
BEAR_RSI_high = 60
BEAR_RSI_low = 20
        
ADX = 3
ADX_high = 70
ADX_low = 50


================================================
FILE: strategy_parameters/RSI_BULL_BEAR_ADX.toml
================================================
SMA_long = 1000
SMA_short = 50

BULL_RSI = 10
BULL_RSI_high = 80
BULL_RSI_low = 60
        
BEAR_RSI = 15
BEAR_RSI_high = 60
BEAR_RSI_low = 20
        
ADX = 3
ADX_high = 70
ADX_low = 50

short = 10
low = 80
mod = 20



================================================
FILE: strategy_parameters/RSI_BULL_BEAR_x2.toml
================================================
# MAJOR SMA TRENDS
MAJOR_SMA_long = 2000
MAJOR_SMA_short = 500

# MAJOR BULL TREND
# SMA Trends
BULL__SMA_long = 1000
BULL__SMA_short = 50
# BULL
BULL__BULL_RSI = 10
BULL__BULL_RSI_high = 80
BULL__BULL_RSI_low = 60
# BEAR
BULL__BEAR_RSI = 15
BULL__BEAR_RSI_high = 50
BULL__BEAR_RSI_low = 20

# MAJOR BEAR TREND
# SMA Trends
BEAR__SMA_long = 1000
BEAR__SMA_short = 50
# BULL
BEAR__BULL_RSI = 10
BEAR__BULL_RSI_high = 80
BEAR__BULL_RSI_low = 60
# BEAR
BEAR__BEAR_RSI = 15
BEAR__BEAR_RSI_high = 50
BEAR__BEAR_RSI_low = 20



================================================
FILE: strategy_parameters/WRSI_BULL_BEAR.toml
================================================
SMA_long = 1000
SMA_short = 50

BULL_RSI = 10
BULL_RSI_high = 80
BULL_RSI_low = 60
        
BEAR_RSI = 15
BEAR_RSI_high = 60
BEAR_RSI_low = 20
        
ADX = 3
ADX_high = 70
ADX_low = 50


================================================
FILE: strategy_parameters/foxhole.toml
================================================
P0 = [-65.536, 65.536]
P1 = [-65.536, 65.536]


================================================
FILE: strategy_parameters/griewangk.toml
================================================
P0 = [-600, 600]
P1 = [-600, 600]
P2 = [-600, 600]
P3 = [-600, 600]
P4 = [-600, 600]
P5 = [-600, 600]
P6 = [-600, 600]
P7 = [-600, 600]
P8 = [-600, 600]
P9 = [-600, 600]


================================================
FILE: strategy_parameters/quartic.toml
================================================
P0 = [-1.28, 1.28]
P1 = [-1.28, 1.28]
P2 = [-1.28, 1.28]
P3 = [-1.28, 1.28]
P4 = [-1.28, 1.28]
P5 = [-1.28, 1.28]
P6 = [-1.28, 1.28]
P7 = [-1.28, 1.28]
P8 = [-1.28, 1.28]
P9 = [-1.28, 1.28]
P10 = [-1.28, 1.28]
P11 = [-1.28, 1.28]
P12 = [-1.28, 1.28]
P13 = [-1.28, 1.28]
P14 = [-1.28, 1.28]
P15 = [-1.28, 1.28]
P16 = [-1.28, 1.28]
P17 = [-1.28, 1.28]
P18 = [-1.28, 1.28]
P19 = [-1.28, 1.28]
P20 = [-1.28, 1.28]
P21 = [-1.28, 1.28]
P22 = [-1.28, 1.28]
P23 = [-1.28, 1.28]
P24 = [-1.28, 1.28]
P25 = [-1.28, 1.28]
P26 = [-1.28, 1.28]
P27 = [-1.28, 1.28]
P28 = [-1.28, 1.28]
P29 = [-1.28, 1.28]


================================================
FILE: strategy_parameters/rastrigin.toml
================================================
P0 = [-5.12, 5.12]
P1 = [-5.12, 5.12]
P2 = [-5.12, 5.12]
P3 = [-5.12, 5.12]
P4 = [-5.12, 5.12]
P5 = [-5.12, 5.12]
P6 = [-5.12, 5.12]
P7 = [-5.12, 5.12]
P8 = [-5.12, 5.12]
P9 = [-5.12, 5.12]
P10 = [-5.12, 5.12]
P11 = [-5.12, 5.12]
P12 = [-5.12, 5.12]
P13 = [-5.12, 5.12]
P14 = [-5.12, 5.12]
P15 = [-5.12, 5.12]
P16 = [-5.12, 5.12]
P17 = [-5.12, 5.12]
P18 = [-5.12, 5.12]
P19 = [-5.12, 5.12]


================================================
FILE: strategy_parameters/rosenbrock.toml
================================================
P0 = [-2.048, 2.048]
P1 = [-2.048, 2.048]


================================================
FILE: strategy_parameters/scalperNEO.toml
================================================
# SMA Trends
SMA_long = 150
SMA_short = 40

# BULL
BULL_RSI = 10
BULL_RSI_high = 80
BULL_RSI_low = 50

# IDLE
IDLE_RSI = 12
IDLE_RSI_high = 65
IDLE_RSI_low = 39

# BEAR
BEAR_RSI = 15
BEAR_RSI_high = 50
BEAR_RSI_low = 25

# ROC
ROC = 6
ROC_lvl = 0
scalperDelay = 7
scalperThresholdPercent = 2


================================================
FILE: strategy_parameters/scalperRBBA.toml
================================================
SMA_long = 1000
SMA_short = 50

BULL_RSI = 10
BULL_RSI_high = 80
BULL_RSI_low = 60
        
BEAR_RSI = 15
BEAR_RSI_high = 60
BEAR_RSI_low = 20
        
ADX = 3
ADX_high = 70
ADX_low = 50

scalperDelay = 7
scalperThresholdPercent = 2


================================================
FILE: strategy_parameters/schwefel.toml
================================================
P0 = [-500, 500]
P1 = [-500, 500]
P2 = [-500, 500]
P3 = [-500, 500]
P4 = [-500, 500]
P5 = [-500, 500]
P6 = [-500, 500]
P7 = [-500, 500]
P8 = [-500, 500]
P9 = [-500, 500]


================================================
FILE: utilities/importer.sh
================================================
#!/bin/bash

# To run GAs one needs candlestick datasets to backtest.
# Grabbing that data on a VPS can be a pain, so thats an automated tool that grabs some interesting datasets;

GekkoPath="${HOME}/gekko"
japonicusRelativeToGekko="../japonicus"
configs=($(ls|grep ".js"))
echo $configs

for conf in "${configs[@]}"
do
node ${GekkoPath}/gekko.js -i -c ${japonicusRelativeToGekko}/utilities/${conf}
done





================================================
FILE: utilities/poloUSDTBTC.js
================================================
// Everything is explained here:
// @link https://gekko.wizb.it/docs/commandline/plugins.html

var config = {};

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                          GENERAL SETTINGS
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
config.trader={};
config.debug = true; // for additional logging / debugging

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                         WATCHING A MARKET
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

config.watch = {

  // see https://gekko.wizb.it/docs/introduction/supported_exchanges.html
  exchange: 'poloniex',
  currency: 'USDT',
  asset: 'BTC',

 }

config.adapter = 'sqlite';

config.sqlite = {
  path: 'plugins/sqlite',

  dataDirectory: 'history',
  version: 0.1,

  journalMode: 'WAL', // setting this to 'DEL' may prevent db locking on windows

  dependencies: []
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                       CONFIGURING IMPORTING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

config.importer = {
  daterange: {
    // NOTE: these dates are in UTC
    from: "2017-01-01 00:00:00"
  }
}

config.candleWriter = {
	enabled: true,
}

// set this to true if you understand that Gekko will
// invest according to how you configured the indicators.
// None of the advice in the output is Gekko telling you
// to take a certain position. Instead it is the result
// of running the indicators you configured automatically.
//
// In other words: Gekko automates your trading strategies,
// it doesn't advice on itself, only set to true if you truly
// understand this.
//
// Not sure? Read this first: https://github.com/askmike/gekko/issues/201
config['I understand that Gekko only automates MY OWN trading strategies'] = false;

module.exports = config;


================================================
FILE: utilities/poloUSDTETH.js
================================================
// Everything is explained here:
// @link https://gekko.wizb.it/docs/commandline/plugins.html

var config = {};

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                          GENERAL SETTINGS
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
config.trader={};
config.debug = true; // for additional logging / debugging

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                         WATCHING A MARKET
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

config.watch = {

  // see https://gekko.wizb.it/docs/introduction/supported_exchanges.html
  exchange: 'poloniex',
  currency: 'USDT',
  asset: 'ETH',

 }

config.adapter = 'sqlite';

config.sqlite = {
  path: 'plugins/sqlite',

  dataDirectory: 'history',
  version: 0.1,

  journalMode: 'WAL', // setting this to 'DEL' may prevent db locking on windows

  dependencies: []
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                       CONFIGURING IMPORTING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

config.importer = {
  daterange: {
    // NOTE: these dates are in UTC
    from: "2017-01-01 00:00:00"
  }
}

config.candleWriter = {
	enabled: true,
}

// set this to true if you understand that Gekko will
// invest according to how you configured the indicators.
// None of the advice in the output is Gekko telling you
// to take a certain position. Instead it is the result
// of running the indicators you configured automatically.
//
// In other words: Gekko automates your trading strategies,
// it doesn't advice on itself, only set to true if you truly
// understand this.
//
// Not sure? Read this first: https://github.com/askmike/gekko/issues/201
config['I understand that Gekko only automates MY OWN trading strategies'] = false;

module.exports = config;


================================================
FILE: utilities/poloUSDTLTC.js
================================================
// Everything is explained here:
// @link https://gekko.wizb.it/docs/commandline/plugins.html

var config = {};

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                          GENERAL SETTINGS
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
config.trader={};
config.debug = true; // for additional logging / debugging

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                         WATCHING A MARKET
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

config.watch = {

  // see https://gekko.wizb.it/docs/introduction/supported_exchanges.html
  exchange: 'poloniex',
  currency: 'USDT',
  asset: 'LTC',

 }


config.adapter = 'sqlite';

config.sqlite = {
  path: 'plugins/sqlite',

  dataDirectory: 'history',
  version: 0.1,

  journalMode: 'WAL', // setting this to 'DEL' may prevent db locking on windows

  dependencies: []
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//                       CONFIGURING IMPORTING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

config.importer = {
  daterange: {
    // NOTE: these dates are in UTC
    from: "2017-01-01 00:00:00"
  }
}

config.candleWriter = {
	enabled: true,
}

// set this to true if you understand that Gekko will
// invest according to how you configured the indicators.
// None of the advice in the output is Gekko telling you
// to take a certain position. Instead it is the result
// of running the indicators you configured automatically.
//
// In other words: Gekko automates your trading strategies,
// it doesn't advice on itself, only set to true if you truly
// understand this.
//
// Not sure? Read this first: https://github.com/askmike/gekko/issues/201
config['I understand that Gekko only automates MY OWN trading strategies'] = false;

module.exports = config;


================================================
FILE: version.py
================================================
#!/bin/python
VERSION = 0.92
Download .txt
gitextract_koczj845/

├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yaml
├── evaluation/
│   ├── __init__.py
│   ├── benchmark/
│   │   ├── __init__.py
│   │   ├── benchmark.py
│   │   └── generateConfig.py
│   └── gekko/
│       ├── API.py
│       ├── __init__.py
│       ├── backtest.py
│       ├── dataset.py
│       ├── datasetOperations.py
│       └── statistics.py
├── exchangerun.csv
├── gekko_evolution.yml
├── japonicus/
│   ├── Settings.py
│   ├── __init__.py
│   ├── configIndicators.py
│   ├── configStrategies.py
│   ├── evolution_generations.py
│   ├── halt.py
│   ├── interface.py
│   ├── japonicus.py
│   └── options.py
├── japonicus-run
├── jlivetrader.py
├── livetrader/
│   ├── exchangeMonitor.py
│   ├── gekkoChecker.py
│   ├── gekkoTrigger.py
│   ├── japonicusResultSelector.py
│   └── strategyRanker.py
├── promoterz/
│   ├── README.md
│   ├── TOMLutils.py
│   ├── __init__.py
│   ├── environment.py
│   ├── evaluationBreak.py
│   ├── evaluationPool.py
│   ├── evolutionHooks.py
│   ├── evolutionToolbox.py
│   ├── functions.py
│   ├── locale.py
│   ├── logAnalysis.py
│   ├── logger.py
│   ├── metaPromoterz.py
│   ├── parameterOperations.py
│   ├── representation/
│   │   ├── Creator.py
│   │   ├── chromosome.py
│   │   ├── deapCreator.py
│   │   └── oldschool.py
│   ├── sequence/
│   │   ├── __init__.py
│   │   ├── locale/
│   │   │   └── standard_loop.py
│   │   └── world/
│   │       └── parallel_world.py
│   ├── statistics.py
│   ├── supplement/
│   │   ├── PRoFIGA.py
│   │   ├── age.py
│   │   └── phenotypicDivergence.py
│   ├── validation.py
│   ├── webServer/
│   │   ├── __init__.py
│   │   ├── core.py
│   │   ├── external_css_list.txt
│   │   ├── graphs.py
│   │   ├── layout.py
│   │   └── promoterz_style.css
│   └── world.py
├── requirements.txt
├── settings/
│   ├── _Global.toml
│   ├── _backtest.toml
│   ├── _bayesian.toml
│   ├── _binance.toml
│   ├── _dataset.toml
│   ├── _evalbreak.toml
│   └── _generation.toml
├── stratego/
│   ├── README.md
│   ├── __init__.py
│   ├── gekko_strategy.py
│   ├── indicator_properties.py
│   └── skeleton/
│       ├── dumbsum.js
│       └── ontrend.js
├── strategy_parameters/
│   ├── BBRSI.toml
│   ├── DUAL_RSI_BULL_BEAR.toml
│   ├── HL_TS.toml
│   ├── NEO.toml
│   ├── NEObigjap.toml
│   ├── PPO.toml
│   ├── RBB_ADX2_BB.toml
│   ├── RSI_BULL_BEAR.toml
│   ├── RSI_BULL_BEAR_ADX.toml
│   ├── RSI_BULL_BEAR_x2.toml
│   ├── WRSI_BULL_BEAR.toml
│   ├── foxhole.toml
│   ├── griewangk.toml
│   ├── quartic.toml
│   ├── rastrigin.toml
│   ├── rosenbrock.toml
│   ├── scalperNEO.toml
│   ├── scalperRBBA.toml
│   └── schwefel.toml
├── utilities/
│   ├── importer.sh
│   ├── poloUSDTBTC.js
│   ├── poloUSDTETH.js
│   └── poloUSDTLTC.js
└── version.py
Download .txt
SYMBOL INDEX (216 symbols across 44 files)

FILE: evaluation/benchmark/benchmark.py
  function evalRosenbrock (line 8) | def evalRosenbrock(parameters):
  function evalGriewangk (line 15) | def evalGriewangk(parameters):
  function evalRastrigin (line 33) | def evalRastrigin(parameters):
  function evalSchwefel (line 45) | def evalSchwefel(parameters):
  function evalQuartic (line 56) | def evalQuartic(parameters):
  function evalFoxHole (line 65) | def evalFoxHole(parameters):
  function Evaluate (line 92) | def Evaluate(genconf, phenotype):

FILE: evaluation/gekko/API.py
  function initializeGekko (line 8) | def initializeGekko():  # not used yet.
  function checkInstance (line 13) | def checkInstance(instanceUrl):
  function httpPost (line 22) | def httpPost(URL, data={}, Verbose=True):
  function loadHostsFile (line 41) | def loadHostsFile(HostsFilePath):

FILE: evaluation/gekko/__init__.py
  class GekkoEvaluator (line 15) | class GekkoEvaluator():
    method __init__ (line 16) | def __init__(self):
  function showBacktestResult (line 30) | def showBacktestResult(backtestResult, dataset=None):
  function parseDatasetInfo (line 51) | def parseDatasetInfo(purpose, candlestickDataset):
  function showPrimaryInfo (line 60) | def showPrimaryInfo(Logger, evolutionDatasets, evaluationDatasets):
  class GekkoEvaluationPool (line 75) | class GekkoEvaluationPool(promoterz.evaluationPool.EvaluationPool):
    method ejectURL (line 79) | def ejectURL(self, Index):
    method distributeIndividuals (line 85) | def distributeIndividuals(self, tosimulation):
  function ResultToIndividue (line 121) | def ResultToIndividue(result, individue):
  function showIndividue (line 127) | def showIndividue(evaldata):
  function validateSettings (line 133) | def validateSettings(settings):
  function launchGekkoChildProcess (line 165) | def launchGekkoChildProcess(settings):

FILE: evaluation/gekko/backtest.py
  function interpreteBacktestProfitv1 (line 5) | def interpreteBacktestProfitv1(backtest):
  function interpreteBacktestProfitv2 (line 9) | def interpreteBacktestProfitv2(backtest):
  function interpreteBacktestProfitv3 (line 13) | def interpreteBacktestProfitv3(backtest):
  function getInterpreterBacktestInfo (line 21) | def getInterpreterBacktestInfo(v):
  function runBacktest (line 31) | def runBacktest(
  function Evaluate (line 70) | def Evaluate(backtestconf, Datasets, phenotype, GekkoInstanceUrl):
  function createConfig (line 113) | def createConfig(

FILE: evaluation/gekko/dataset.py
  function getAllScanset (line 7) | def getAllScanset(GekkoURL):
  function selectCandlestickData (line 13) | def selectCandlestickData(GekkoURL,
  function getCandles (line 93) | def getCandles(globalconf, DateRange, Dataset, size=100):
  function getDateRange (line 112) | def getDateRange(Limits, deltaDays=3):
  function getRandomDateRange (line 122) | def getRandomDateRange(Limits, deltaDays):
  function epochToString (line 140) | def epochToString(D):

FILE: evaluation/gekko/datasetOperations.py
  class CandlestickDataset (line 6) | class CandlestickDataset():
    method __init__ (line 7) | def __init__(self, specifications, daterange):
    method restrain (line 11) | def restrain(self, deltaDays):
    method textDaterange (line 19) | def textDaterange(self):
    method textSpecifications (line 22) | def textSpecifications(self):
    method __str__ (line 29) | def __str__(self):
  function getRandomSectorOfDataset (line 33) | def getRandomSectorOfDataset(sourceDataset, deltaDays):
  function getLocaleDataset (line 43) | def getLocaleDataset(World, Type='evolution'):
  function dateRangeToText (line 56) | def dateRangeToText(dateRange):

FILE: evaluation/gekko/statistics.py
  function compileStats (line 26) | def compileStats(locale):
  function showStatistics (line 49) | def showStatistics(locale):

FILE: japonicus/Settings.py
  class makeSettings (line 12) | class makeSettings(dict):
    method __init__ (line 13) | def __init__(self, entries):
  function getSettings (line 21) | def getSettings(SettingsFiles=[], specific=None):
  function loadTomlSettings (line 62) | def loadTomlSettings(settingsDivisionName):
  function get_configjs (line 76) | def get_configjs(filename="example-config.js"):

FILE: japonicus/evolution_generations.py
  function indicatorEvaluate (line 22) | def indicatorEvaluate(
  function standardEvaluate (line 39) | def standardEvaluate(constructPhenotype,
  function benchmarkEvaluate (line 49) | def benchmarkEvaluate(constructPhenotype,
  function grabDatasets (line 59) | def grabDatasets(conf):
  function Generations (line 103) | def Generations(

FILE: japonicus/halt.py
  function userExit (line 22) | def userExit(x, y):

FILE: japonicus/interface.py
  function showTitleDisclaimer (line 6) | def showTitleDisclaimer(backtestsettings, VERSION):

FILE: japonicus/japonicus.py
  function launchWebEvolutionaryInfo (line 21) | def launchWebEvolutionaryInfo():
  function buildSettingsOptions (line 38) | def buildSettingsOptions(optionparser, settingSubsets):
  function loadEvaluationModule (line 58) | def loadEvaluationModule():
  class JaponicusSession (line 67) | class JaponicusSession():
    method __init__ (line 69) | def __init__(self, EvaluationModule, settings, options):

FILE: livetrader/exchangeMonitor.py
  class Exchange (line 8) | class Exchange():
    method __init__ (line 9) | def __init__(self, name):
    method getCotations (line 20) | def getCotations(self):
    method parseAsset (line 23) | def parseAsset(self, Asset):
    method fetchAssetPrices (line 27) | def fetchAssetPrices(self, Symbols):
    method getAveragePrices (line 35) | def getAveragePrices(self):
    method getMarketsOfCurrency (line 42) | def getMarketsOfCurrency(self, currency='USDT'):
    method getUserBalance (line 45) | def getUserBalance(self, Verbose=False):
    method getAssets (line 82) | def getAssets(self):
    method parseAssets (line 86) | def parseAssets(self, assets):
    method generateMarketsJson (line 99) | def generateMarketsJson(self, Assets):
    method getRecentOrders (line 145) | def getRecentOrders(self, pastTimeRangeDays=2):
    method getPriceHistory (line 156) | def getPriceHistory(self):

FILE: livetrader/gekkoChecker.py
  function calculateMostIndicatedAssets (line 23) | def calculateMostIndicatedAssets(exchange):
  function stopGekkoBots (line 32) | def stopGekkoBots():
  function interpreteRunningBotStatistics (line 52) | def interpreteRunningBotStatistics(runningBots):
  function getParameterSettingsPath (line 78) | def getParameterSettingsPath(parameterName):
  function operateStrategyScores (line 84) | def operateStrategyScores(exchange, ranker,
  function checkGekkoRunningBots (line 145) | def checkGekkoRunningBots(exchange, ranker, options):

FILE: livetrader/gekkoTrigger.py
  function runTradingBot (line 10) | def runTradingBot(botSpecifications, Strategy, options, TradingBot=False):
  function getTraderBaseParameters (line 85) | def getTraderBaseParameters():
  function getWatchSettings (line 115) | def getWatchSettings(coinInfo):
  function checkWatcherExists (line 126) | def checkWatcherExists(Watch):
  function getRunningGekkos (line 145) | def getRunningGekkos():
  function getWatcherBaseParameters (line 155) | def getWatcherBaseParameters():
  function launchBatchTradingBots (line 167) | def launchBatchTradingBots(assetCurrencyPairs, Stratlist, options):

FILE: livetrader/japonicusResultSelector.py
  function readResultFolder (line 10) | def readResultFolder(strategyName, runLogFolderPath, retrievalCount=1):
  function sweepLogFolder (line 61) | def sweepLogFolder():

FILE: livetrader/strategyRanker.py
  class strategyRanker (line 7) | class strategyRanker():
    method __init__ (line 8) | def __init__(self):
    method loadStrategyRankings (line 11) | def loadStrategyRankings(self):
    method saveStrategyRankings (line 18) | def saveStrategyRankings(self):
    method selectStrategyToRun (line 26) | def selectStrategyToRun(self, sigma=10):
  class strategyParameterSet (line 37) | class strategyParameterSet():
    method __init__ (line 38) | def __init__(self, jsonData):
    method fromJson (line 42) | def fromJson(self, jsonData):
    method toJson (line 46) | def toJson(self):
    method loadParameterSet (line 52) | def loadParameterSet(self):
    method getScore (line 55) | def getScore(self):

FILE: promoterz/TOMLutils.py
  function preprocessTOMLFile (line 5) | def preprocessTOMLFile(filepath):
  function TOMLToParameters (line 10) | def TOMLToParameters(TOMLDATA):
  function parametersToTOML (line 22) | def parametersToTOML(Settings):

FILE: promoterz/environment.py
  class Environment (line 4) | class Environment():
    method __init__ (line 5) | def __init__(self, propertyGenenerator):

FILE: promoterz/evaluationBreak.py
  function showResults (line 13) | def showResults(World):
  function stratSettingsProofOfViability (line 164) | def stratSettingsProofOfViability(World, Individual, Datasets):

FILE: promoterz/evaluationPool.py
  class EvaluationPool (line 10) | class EvaluationPool():
    method __init__ (line 12) | def __init__(self,
    method evaluateBackend (line 23) | def evaluateBackend(self, datasets, I, inds):
    method evaluatePopulation (line 38) | def evaluatePopulation(self, locale):

FILE: promoterz/evolutionHooks.py
  function immigrateHoF (line 15) | def immigrateHoF(HallOfFame, population):
  function immigrateRandom (line 26) | def immigrateRandom(populate, nb_range, population):  # (populate function)
  function filterAwayWorst (line 32) | def filterAwayWorst(population, N=5):
  function filterAwayThreshold (line 38) | def filterAwayThreshold(locale, Threshold, min_nb_inds):
  function filterAwayTradeCounts (line 43) | def filterAwayTradeCounts(locale, ThresholdRange, min_nb_inds):
  function filterAwayRoundtripDuration (line 55) | def filterAwayRoundtripDuration(locale, ThresholdRange, min_nb_inds):
  function populationFilter (line 68) | def populationFilter(locale, filterFunction, min_nb_inds):
  function evaluatePopulation (line 87) | def evaluatePopulation(locale):
  function getLocaleEvolutionToolbox (line 98) | def getLocaleEvolutionToolbox(World, locale):
  function getGlobalToolbox (line 120) | def getGlobalToolbox(representationModule):
  function getFitness (line 140) | def getFitness(individual):
  function selectCriteria (line 144) | def selectCriteria(ind):
  function selBest (line 148) | def selBest(individuals, number):
  function Tournament (line 153) | def Tournament(individuals, finalselect, tournsize):

FILE: promoterz/evolutionToolbox.py
  function getExtraTools (line 5) | def getExtraTools(HallOfFame, W):

FILE: promoterz/functions.py
  function PrepareAndEvaluate (line 11) | def PrepareAndEvaluate(constructPhenotype, evaluationMethod, Individual):
  function selectRepresentationMethod (line 16) | def selectRepresentationMethod(methodname):

FILE: promoterz/locale.py
  class Locale (line 8) | class Locale():
    method __init__ (line 10) | def __init__(self, World, name, position, loop):
    method run (line 40) | def run(self):

FILE: promoterz/logger.py
  class Logger (line 7) | class Logger():
    method __init__ (line 8) | def __init__(self, logfilename):
    method log (line 19) | def log(self, message, target="Body", show=True, replace=False):
    method updateFile (line 34) | def updateFile(self):
    method write_evolution_logs (line 43) | def write_evolution_logs(self, i, stats, localeName):
    method saveParameters (line 52) | def saveParameters(self, filename, content):

FILE: promoterz/metaPromoterz.py
  function generateCommandLineArguments (line 11) | def generateCommandLineArguments(parser, settings):
  function applyCommandLineOptionsToSettings (line 29) | def applyCommandLineOptionsToSettings(options, settings):

FILE: promoterz/parameterOperations.py
  function flattenParameters (line 4) | def flattenParameters(Parameters):
  function expandNestedParameters (line 19) | def expandNestedParameters(Parameters):
  function parameterValuesToRangeOfValues (line 37) | def parameterValuesToRangeOfValues(TargetParameters, Spread):

FILE: promoterz/representation/Creator.py
  function init (line 6) | def init(fitness, extraParameters):

FILE: promoterz/representation/chromosome.py
  function constructPhenotype (line 15) | def constructPhenotype(stratSettings, chrconf, Individue):
  function getToolbox (line 36) | def getToolbox(Strategy, genconf, Attributes):
  function initPromoterMap (line 53) | def initPromoterMap(ParameterRanges):
  function initChromosomes (line 65) | def initChromosomes(PromoterMap, chrconf):
  function initInd (line 81) | def initInd(Individual, PromoterMap, chrconf):
  function generateUID (line 88) | def generateUID():
  function chromossomeCrossover (line 94) | def chromossomeCrossover(chr1, chr2):
  function pachytene (line 111) | def pachytene(ind1, ind2):
  function mutate (line 126) | def mutate(ind, mutpb=0.001, mutagg=12):
  function clone (line 137) | def clone(Chr):  #!!review this

FILE: promoterz/representation/deapCreator.py
  class _numpy_array (line 52) | class _numpy_array(numpy.ndarray):
    method __deepcopy__ (line 53) | def __deepcopy__(self, memo):
    method __new__ (line 63) | def __new__(cls, iterable):
    method __setstate__ (line 68) | def __setstate__(self, state):
    method __reduce__ (line 71) | def __reduce__(self):
  class _array (line 76) | class _array(array.array):
    method __new__ (line 78) | def __new__(cls, seq=()):
    method __deepcopy__ (line 81) | def __deepcopy__(self, memo):
    method __reduce__ (line 91) | def __reduce__(self):
  class CreatorMeta (line 95) | class CreatorMeta(type):
    method __new__ (line 96) | def __new__(meta, name, base, dct):
    method __init__ (line 99) | def __init__(cls, name, base, dct):
    method __reduce__ (line 125) | def __reduce__(cls):
  function meta_creator (line 130) | def meta_creator(name, base, dct):
  function create (line 135) | def create(name, base, **kargs):

FILE: promoterz/representation/oldschool.py
  function constructPhenotype (line 16) | def constructPhenotype(stratSettings, individue):
  function createRandomVarList (line 30) | def createRandomVarList(IndSize):
  function initInd (line 35) | def initInd(Criterion, Attributes):
  function getToolbox (line 42) | def getToolbox(Strategy, genconf, Attributes):

FILE: promoterz/sequence/locale/standard_loop.py
  function checkPopulation (line 13) | def checkPopulation(population, message):
  function execute (line 18) | def execute(World, locale):

FILE: promoterz/sequence/world/parallel_world.py
  function execute (line 8) | def execute(World):

FILE: promoterz/statistics.py
  function getStatisticsMeter (line 7) | def getStatisticsMeter():

FILE: promoterz/supplement/PRoFIGA.py
  function calculatePRoFIGA (line 3) | def calculatePRoFIGA(beta, EPOCH, NBEPOCH, oldstats, Stats):

FILE: promoterz/supplement/age.py
  function _maturePopulation (line 5) | def _maturePopulation(population):
  function _checkRetirement (line 14) | def _checkRetirement(individue, statistics, ageBoundary):
  function _killElders (line 34) | def _killElders(population, statistics, ageBoundary):
  function ageZero (line 42) | def ageZero(population):
  function populationAges (line 47) | def populationAges(ageBoundary, population, averageScore):

FILE: promoterz/supplement/phenotypicDivergence.py
  function checkPhenotypicDivergence (line 7) | def checkPhenotypicDivergence(constructPhenotype, indA, indB):
  function populationPhenotypicDivergence (line 18) | def populationPhenotypicDivergence(constructPhenotype, population, delpe...

FILE: promoterz/validation.py
  function checkPhenotypeParameterIntegrity (line 5) | def checkPhenotypeParameterIntegrity(TargetParameters, phenotype):
  function checkPhenotypeAttributeRanges (line 18) | def checkPhenotypeAttributeRanges(TargetParameters, phenotype, tolerance...
  function validatePopulation (line 32) | def validatePopulation(IndividualToSettings, TargetParameters, population):

FILE: promoterz/webServer/core.py
  function build_server (line 26) | def build_server(webpageTitle):

FILE: promoterz/webServer/graphs.py
  function updateWorldGraph (line 8) | def updateWorldGraph(app, WORLD):
  function updateLocaleGraph (line 42) | def updateLocaleGraph(app, LOCALE):
  function updateEvalbreakGraph (line 130) | def updateEvalbreakGraph(app, EvaluationSummary):

FILE: promoterz/webServer/layout.py
  function getLayout (line 17) | def getLayout(app):
  function getHeader (line 26) | def getHeader(app):
  function getCommon (line 73) | def getCommon(app):
  function getEvalbreak (line 80) | def getEvalbreak(app):
  function getResults (line 86) | def getResults(app):

FILE: promoterz/world.py
  class World (line 10) | class World():
    method __init__ (line 11) | def __init__(
    method generateLocale (line 46) | def generateLocale(self):
    method migration (line 59) | def migration(self, source, target, number_range):
    method explodeLocale (line 68) | def explodeLocale(self, explLocale):
    method runEpoch (line 96) | def runEpoch(self):
    method calculateDistance (line 124) | def calculateDistance(point1, point2):
    method seedEnvironment (line 130) | def seedEnvironment(self):
    method loadDatasetForLocalePosition (line 142) | def loadDatasetForLocalePosition(self, position):
    method localeWalk (line 148) | def localeWalk(self, locale):

FILE: stratego/gekko_strategy.py
  class StrategyFileManager (line 21) | class StrategyFileManager():
    method __init__ (line 23) | def __init__(self, gekkoPath, indicatorSettings):
    method selectIndicator (line 51) | def selectIndicator(self, chosenIndicators, phenotype, Type):
    method checkStrategy (line 72) | def checkStrategy(self, phenotype):
    method interpreteSkeletonHeader (line 104) | def interpreteSkeletonHeader(self, header):
    method createStrategyFile (line 114) | def createStrategyFile(self, Indicators, stratpath):
    method _createStrategyFile (line 124) | def _createStrategyFile(self, Indicators, stratpath):
Condensed preview — 104 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (198K chars).
[
  {
    "path": ".gitignore",
    "chars": 3578,
    "preview": "### https://raw.github.com/github/gitignore/1a92ca87b787b6a0c68eb10371ebd0bfd823db9b/Global/Windows.gitignore\n\n# Windows"
  },
  {
    "path": "Dockerfile",
    "chars": 752,
    "preview": "FROM python:3.6.6-jessie\n\n\nENV LANG en_US.UTF-8\n\n# install dependencies;\n#RUN apt-get update -y\n#RUN apt-get install sof"
  },
  {
    "path": "LICENSE",
    "chars": 1099,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014-2017 Mike van Rossum mike@mvr.me\n\nPermission is hereby granted, free of charge"
  },
  {
    "path": "README.md",
    "chars": 4854,
    "preview": "### What is japonicus and what it does\nThis is an implementation of genetic algorithm & bayesian evolution to develop st"
  },
  {
    "path": "docker-compose.yaml",
    "chars": 324,
    "preview": "version: '3'\nservices:\n  gekko:\n    image: gekko\n    volumes:\n      - gekko-dir:/usr/src/app\n    ports:\n      - \"3000:30"
  },
  {
    "path": "evaluation/__init__.py",
    "chars": 57,
    "preview": "#!/bin/python\nfrom .import gekko\nfrom . import benchmark\n"
  },
  {
    "path": "evaluation/benchmark/__init__.py",
    "chars": 39,
    "preview": "#!/bin/python\n\nfrom . import benchmark\n"
  },
  {
    "path": "evaluation/benchmark/benchmark.py",
    "chars": 2541,
    "preview": "#!/bin/python\n\n# source https://www.researchgate.net/publication/27382766_On_benchmarking_functions_for_genetic_algorith"
  },
  {
    "path": "evaluation/benchmark/generateConfig.py",
    "chars": 406,
    "preview": "#!/bin/python\nimport pytoml\n\nNBP = 30\nPRANGE = [-1.28, 1.28]\n\nNBP = 25\nPRANGE = [-65536, 65536]\n\nNBP = 10\nPRANGE = [-500"
  },
  {
    "path": "evaluation/gekko/API.py",
    "chars": 1181,
    "preview": "#!/bin/python\nimport os\nimport requests\nimport json\nfrom subprocess import Popen, PIPE\n\n\ndef initializeGekko():  # not u"
  },
  {
    "path": "evaluation/gekko/__init__.py",
    "chars": 5035,
    "preview": "#!/bin/python\nimport os\nimport subprocess\n\nfrom .import API\nfrom .import dataset\nfrom .import backtest\nfrom .import data"
  },
  {
    "path": "evaluation/gekko/backtest.py",
    "chars": 5381,
    "preview": "#!/bin/python\nfrom .API import httpPost\n\n\ndef interpreteBacktestProfitv1(backtest):\n    return backtest['relativeProfit'"
  },
  {
    "path": "evaluation/gekko/dataset.py",
    "chars": 4448,
    "preview": "#!/bin/python\nimport random\nimport datetime\nfrom .API import httpPost\n\n\ndef getAllScanset(GekkoURL):\n    URL = GekkoURL "
  },
  {
    "path": "evaluation/gekko/datasetOperations.py",
    "chars": 1921,
    "preview": "#!/bin/python\nimport evaluation\nimport random\n\n\nclass CandlestickDataset():\n    def __init__(self, specifications, dater"
  },
  {
    "path": "evaluation/gekko/statistics.py",
    "chars": 2549,
    "preview": "#!/bin/python\n\nfrom deap import tools\nimport numpy as np\n\nepochStatisticsNames = {\n    'avg': 'Average profit',\n    'std"
  },
  {
    "path": "exchangerun.csv",
    "chars": 279,
    "preview": "EXCHANGE,CURRENCY,ASSET,STRATEGY\nbinance,usdt,btc,RSI_BULL_BEAR_ADX\nbinance,usdt,bcc,RSI_BULL_BEAR_ADX\nbinance,usdt,ltc,"
  },
  {
    "path": "gekko_evolution.yml",
    "chars": 1372,
    "preview": "- name: prepare machine software and install Gekko Trading Bot\n  hosts: all\n  remote_user: ec2-user \n  become_method: su"
  },
  {
    "path": "japonicus/Settings.py",
    "chars": 2068,
    "preview": "#!/bin/python\nimport js2py\nfrom pathlib import Path\n\nfrom .configStrategies import cS\nfrom .configIndicators import cI\n\n"
  },
  {
    "path": "japonicus/__init__.py",
    "chars": 86,
    "preview": "#!/bin/python\n\nfrom .japonicus import *\nfrom . import options\nfrom . import interface\n"
  },
  {
    "path": "japonicus/configIndicators.py",
    "chars": 1693,
    "preview": "#!/bin/python\ncI = {\n    \"ADX\": {\"active\": True, \"period\": 14, \"thresholds.up\": 70, \"thresholds.down\": 50},\n    \"ATR\": {"
  },
  {
    "path": "japonicus/configStrategies.py",
    "chars": 6667,
    "preview": "#!/bin/python\n\nNEG = lambda v: (-v[1], -v[0])\ncS = {\n    # Define values for strat settings for strategies to be used\n  "
  },
  {
    "path": "japonicus/evolution_generations.py",
    "chars": 9261,
    "preview": "#!/bin/python\nimport json\nimport time\nimport sys\n\nimport promoterz\nimport evaluation\n\nfrom . import interface\n\nfrom .Set"
  },
  {
    "path": "japonicus/halt.py",
    "chars": 730,
    "preview": "#!/bin/python\n\nimport signal\nimport sys\n\nimport psutil\nimport os\nimport time\n\nM = sys.version_info.major\nm = sys.version"
  },
  {
    "path": "japonicus/interface.py",
    "chars": 1115,
    "preview": "#!/bin/python\nimport evaluation\n\n\n\ndef showTitleDisclaimer(backtestsettings, VERSION):\n    TITLE = \"\"\"\n        ██╗ █████"
  },
  {
    "path": "japonicus/japonicus.py",
    "chars": 5398,
    "preview": "#!/bin/python\n\nfrom . import halt, Settings, interface\n\nfrom time import sleep\nimport random\nfrom threading import Threa"
  },
  {
    "path": "japonicus/options.py",
    "chars": 1388,
    "preview": "\nimport optparse\n\nparser = optparse.OptionParser()\nparser.add_option(\n    '-g', '--genetic', dest='genetic_algorithm', a"
  },
  {
    "path": "japonicus-run",
    "chars": 299,
    "preview": "#!/bin/python\nimport os\n\nimport japonicus\nimport evaluation\nos.chdir(os.path.dirname(os.path.realpath(__file__)))\n\n\nsett"
  },
  {
    "path": "jlivetrader.py",
    "chars": 3224,
    "preview": "#!/bin/python\nimport os\nimport optparse\nimport json\n\nimport livetrader.exchangeMonitor\nimport livetrader.gekkoTrigger\nim"
  },
  {
    "path": "livetrader/exchangeMonitor.py",
    "chars": 4961,
    "preview": "#!/bin/python\nimport ccxt\nimport json\nfrom japonicus import Settings\nimport time\n\n\nclass Exchange():\n    def __init__(se"
  },
  {
    "path": "livetrader/gekkoChecker.py",
    "chars": 7092,
    "preview": "#!/bin/python\n\nfrom . import gekkoTrigger\n\ntry:\n    from . import assetAllocator\nexcept Exception:\n    pass\n\nfrom dateut"
  },
  {
    "path": "livetrader/gekkoTrigger.py",
    "chars": 4831,
    "preview": "#!/bin/python\nimport time\nfrom evaluation.gekko.API import httpPost\nfrom evaluation.gekko.dataset import epochToString\ni"
  },
  {
    "path": "livetrader/japonicusResultSelector.py",
    "chars": 1858,
    "preview": "#!/bin/python\nimport os\nimport csv\nimport shutil\nimport names\n\nfrom . import exchangeMonitor\n\n\ndef readResultFolder(stra"
  },
  {
    "path": "livetrader/strategyRanker.py",
    "chars": 1628,
    "preview": "#!/bin/python\nimport json\nimport pytoml\nimport random\n\n\nclass strategyRanker():\n    def __init__(self):\n        self.Str"
  },
  {
    "path": "promoterz/README.md",
    "chars": 492,
    "preview": "A python module specialized on genetic algorithms using various representations. \nIntended to evolve a dict of parameter"
  },
  {
    "path": "promoterz/TOMLutils.py",
    "chars": 515,
    "preview": "#!/bin/python\nimport re\nimport pytoml\n\ndef preprocessTOMLFile(filepath):\n    f = open(filepath)\n    return f\n\n\ndef TOMLT"
  },
  {
    "path": "promoterz/__init__.py",
    "chars": 322,
    "preview": "#!/bin/python\nfrom .import functions\n\nfrom .import supplement, validation, parameterOperations\nfrom .import evolutionHoo"
  },
  {
    "path": "promoterz/environment.py",
    "chars": 104,
    "preview": "#!/bin/python\n\n\nclass Environment():\n    def __init__(self, propertyGenenerator):\n        self.w = None\n"
  },
  {
    "path": "promoterz/evaluationBreak.py",
    "chars": 7001,
    "preview": "#!/bin/python\nimport random\nimport json\nimport csv\nfrom deap import tools\n\n\nimport promoterz\nimport evaluation\nfrom . im"
  },
  {
    "path": "promoterz/evaluationPool.py",
    "chars": 3354,
    "preview": "#!/bin/python\nimport time\nimport random\nimport itertools\n\nfrom multiprocessing import Pool, TimeoutError\nfrom multiproce"
  },
  {
    "path": "promoterz/evolutionHooks.py",
    "chars": 5063,
    "preview": "#!/bin/python\nfrom deap import base, tools\nfrom copy import deepcopy\n\nimport random\n\nimport promoterz.supplement.age\nimp"
  },
  {
    "path": "promoterz/evolutionToolbox.py",
    "chars": 115,
    "preview": "#!/bin/python\nfrom deap import base\n\n\ndef getExtraTools(HallOfFame, W):\n    T = base.Toolbox()\n    T.register('q')\n"
  },
  {
    "path": "promoterz/functions.py",
    "chars": 439,
    "preview": "#!/bin/python\nimport random\nfrom deap import base\nfrom deap import creator\nfrom deap import tools\nfrom copy import deepc"
  },
  {
    "path": "promoterz/locale.py",
    "chars": 1484,
    "preview": "#!/bin/python\nfrom deap import tools\n\nfrom . import evolutionHooks\nfrom . import statistics\n\n\nclass Locale():\n\n    def _"
  },
  {
    "path": "promoterz/logAnalysis.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "promoterz/logger.py",
    "chars": 1693,
    "preview": "#!/bin/python\nimport datetime\nimport os\nimport csv\n\n\nclass Logger():\n    def __init__(self, logfilename):\n        date ="
  },
  {
    "path": "promoterz/metaPromoterz.py",
    "chars": 1250,
    "preview": "#!/bin/python\n\n# this file contains functions for 'meta genetic algorithm',\n# this acts to allow settings value manipula"
  },
  {
    "path": "promoterz/parameterOperations.py",
    "chars": 1291,
    "preview": "\n\n#!/bin/python\ndef flattenParameters(Parameters):\n    result = {}\n\n    def iter(D, path= []):\n        for q in D.keys()"
  },
  {
    "path": "promoterz/representation/Creator.py",
    "chars": 275,
    "preview": "#!/bin/python\nfrom .import deapCreator as creator\nfrom deap import base\n\n\ndef init(fitness, extraParameters):\n    creato"
  },
  {
    "path": "promoterz/representation/chromosome.py",
    "chars": 4685,
    "preview": "#!/bin/python\nfrom deap import base\nfrom deap import tools\n\nfrom copy import deepcopy\nimport random\n\nfrom . .import para"
  },
  {
    "path": "promoterz/representation/deapCreator.py",
    "chars": 7054,
    "preview": "#    This file is part of DEAP.\n#\n#    DEAP is free software: you can redistribute it and/or modify\n#    it under the te"
  },
  {
    "path": "promoterz/representation/oldschool.py",
    "chars": 1512,
    "preview": "#!/bin/python\nimport random\nimport json\nimport os\n\nfrom copy import deepcopy\n\nfrom .import Creator\nfrom deap import base"
  },
  {
    "path": "promoterz/sequence/__init__.py",
    "chars": 83,
    "preview": "#!/bin/python\n\nfrom .locale import standard_loop\nfrom .world import parallel_world\n"
  },
  {
    "path": "promoterz/sequence/locale/standard_loop.py",
    "chars": 6163,
    "preview": "#!/bin/python\nfrom deap import tools\nfrom copy import deepcopy\nimport random\nfrom deap import algorithms\n\nfrom ... impor"
  },
  {
    "path": "promoterz/sequence/world/parallel_world.py",
    "chars": 1508,
    "preview": "#!/bin/python\nimport random\nimport itertools\nimport math\nimport time\n\n\ndef execute(World):\n\n    # --APPLY MIGRATION BETW"
  },
  {
    "path": "promoterz/statistics.py",
    "chars": 304,
    "preview": "#!/bin/python\n\nimport numpy as np\nfrom deap import tools\n\n\ndef getStatisticsMeter():\n    stats = tools.Statistics(lambda"
  },
  {
    "path": "promoterz/supplement/PRoFIGA.py",
    "chars": 216,
    "preview": "#!/bin/python\n\ndef calculatePRoFIGA(beta, EPOCH, NBEPOCH, oldstats, Stats):\n    remainingEPOCH_NB = NBEPOCH - EPOCH\n\n   "
  },
  {
    "path": "promoterz/supplement/age.py",
    "chars": 1494,
    "preview": "# 1/bin/python\nfrom deap import base\n\n\ndef _maturePopulation(population):\n    for W in range(len(population)):\n        t"
  },
  {
    "path": "promoterz/supplement/phenotypicDivergence.py",
    "chars": 975,
    "preview": "#!/bin/python\nfrom deap import tools\nfrom . .import parameterOperations\nimport random\n\n\ndef checkPhenotypicDivergence(co"
  },
  {
    "path": "promoterz/validation.py",
    "chars": 1754,
    "preview": "#!/bin/python\nfrom .parameterOperations import flattenParameters\n\n\ndef checkPhenotypeParameterIntegrity(TargetParameters"
  },
  {
    "path": "promoterz/webServer/__init__.py",
    "chars": 33,
    "preview": "#!/bin/python\n\nfrom .import core\n"
  },
  {
    "path": "promoterz/webServer/core.py",
    "chars": 3166,
    "preview": "#!/bin/python\nimport os\nimport re\nimport datetime\n\nimport flask\nimport dash\n\nfrom dash.dependencies import Input, Output"
  },
  {
    "path": "promoterz/webServer/external_css_list.txt",
    "chars": 192,
    "preview": "https://fonts.googleapis.com/css?family=Overpass:400,400i,700,700i\nhttps://cdn.jsdelivr.net/gh/plotly/dash-app-styleshee"
  },
  {
    "path": "promoterz/webServer/graphs.py",
    "chars": 4130,
    "preview": "#!/bin/python\n\nimport dash_core_components as dcc\n\nfrom evaluation.gekko.statistics import epochStatisticsNames, periodi"
  },
  {
    "path": "promoterz/webServer/layout.py",
    "chars": 2566,
    "preview": "#!/bin/python\n\nimport dash_core_components as dcc\nimport dash_html_components as html\nimport datetime\n\n\nallStyle = {\n   "
  },
  {
    "path": "promoterz/webServer/promoterz_style.css",
    "chars": 90,
    "preview": ".unimplemented {\n    background-color: #666;\n} \n\n.showTime {\n    display: inline-block;\n}\n"
  },
  {
    "path": "promoterz/world.py",
    "chars": 4957,
    "preview": "#!/bin/python\nimport random\n\nimport time\nimport math\n\nfrom . import locale\n\n\nclass World():\n    def __init__(\n          "
  },
  {
    "path": "requirements.txt",
    "chars": 381,
    "preview": "ccxt==1.13.139\npandas_datareader==0.5.0\nnumpy==1.16.2\ntulipy==0.2\npandas==0.18.1\ndeap==1.2.2\nscipy==0.19.0\npytoml==0.1.1"
  },
  {
    "path": "settings/_Global.toml",
    "chars": 461,
    "preview": "gekkoPath = '$HOME/gekko'\nconfigFilename = 'example-config.js'\nlog_name = 'evolution_gen.csv'\n\n# Hosts list of remote ma"
  },
  {
    "path": "settings/_backtest.toml",
    "chars": 709,
    "preview": "# show gekko verbose (strat info) - gekko must start with -d flag;\ngekkoDebug = 0\n# time window size on days of candlest"
  },
  {
    "path": "settings/_bayesian.toml",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "settings/_binance.toml",
    "chars": 258,
    "preview": "credentialsFilePath = \"\"\nstrategyRunTimePeriodHours = 12\nstrategySelectorSigma = 10\n# following option points to binance"
  },
  {
    "path": "settings/_dataset.toml",
    "chars": 539,
    "preview": "# span in days from the end of dataset to the beggining. Or zero.\n# (to restrain length);\ndataset_span = 0\n# span for ev"
  },
  {
    "path": "settings/_evalbreak.toml",
    "chars": 399,
    "preview": "# number of individues selected by score on each evaluation break for each locale;\nNBBESTINDS = 1\n# number of individues"
  },
  {
    "path": "settings/_generation.toml",
    "chars": 2515,
    "preview": "\n# Verbose single evaluation results;\nshowIndividualEvaluationInfo = false\n\n# if parameter is set to value rather than t"
  },
  {
    "path": "stratego/README.md",
    "chars": 470,
    "preview": "### Usage\n\nThis is a submodule of japonicus. This takes care of on-the-fly strategy creation and management.\nIts on a ve"
  },
  {
    "path": "stratego/__init__.py",
    "chars": 43,
    "preview": "# 1/bin/python\nfrom .import gekko_strategy\n"
  },
  {
    "path": "stratego/gekko_strategy.py",
    "chars": 6258,
    "preview": "#!/bin/python\nimport os\nimport random\nimport hashlib\nimport re\nfrom collections import OrderedDict\n\n# from . import Sett"
  },
  {
    "path": "stratego/indicator_properties.py",
    "chars": 1188,
    "preview": "#!/bin/python\nstdResult = [\"> this.settings.{i}.thresholds.up\", \"< this.settings.{i}.thresholds.down\"]\nagainstPrice = [\""
  },
  {
    "path": "stratego/skeleton/dumbsum.js",
    "chars": 1657,
    "preview": "// helpers\nvar _ = require('lodash');\nvar log = require('../../core/log.js');\n\n// let's create our own method\nvar method"
  },
  {
    "path": "stratego/skeleton/ontrend.js",
    "chars": 4459,
    "preview": "/*\n  skeleton adapted from former strategy:\n\n\tRSI Bull and Bear + ADX modifier\n\t1. Use different RSI-strategies dependin"
  },
  {
    "path": "strategy_parameters/BBRSI.toml",
    "chars": 116,
    "preview": "interval = 14\n\n[thresholds]\nlow = 40\nhigh = 40\npersistence = 9\n\n[bbands]\nTimePeriod = 20\nNbDevUp = 0.7\nNbDevDn = 0.7"
  },
  {
    "path": "strategy_parameters/DUAL_RSI_BULL_BEAR.toml",
    "chars": 397,
    "preview": "[RBB1]\nSMA_long = 1000\nSMA_short = 50\n#BULL\nBULL_RSI = 10\nBULL_RSI_high = 80\nBULL_RSI_low = 60\n#BEAR   \nBEAR_RSI = 15\nBE"
  },
  {
    "path": "strategy_parameters/HL_TS.toml",
    "chars": 448,
    "preview": "# Minimum volume needed to enter a trade\nMin24hUSDVolume = 500000\nRollingVolumeHours = 24\nCurrencyPrice = 9000\nCandleSiz"
  },
  {
    "path": "strategy_parameters/NEO.toml",
    "chars": 535,
    "preview": "# Source: https://raw.githubusercontent.com/gcobs0834/gekko/develop/config/strategies/NEO.toml\n# SMA Trends\nSMA_long = 1"
  },
  {
    "path": "strategy_parameters/NEObigjap.toml",
    "chars": 458,
    "preview": "# SETTINGS FOUND FOR NEO STRAT AT EPOCH 15.000;\n# INTERNAL BACKTESTS RETURNED GREAT SCORE;\nBEAR_RSI_low = 23.10606060606"
  },
  {
    "path": "strategy_parameters/PPO.toml",
    "chars": 86,
    "preview": "short = 12\nlong = 26\nsignal = 9\n\n[thresholds]\ndown = -0.025\nup = 0.025\npersistence = 2"
  },
  {
    "path": "strategy_parameters/RBB_ADX2_BB.toml",
    "chars": 346,
    "preview": "[ADX]\nadx = 3.0\nhigh = 50\n\n[BBands]\nNbDevDn = 2.0\nNbDevUp = 2.0\nTimePeriod = 20.0\n\n[BBtrend]\nbearPersistence = 16\nbullPe"
  },
  {
    "path": "strategy_parameters/RSI_BULL_BEAR.toml",
    "chars": 194,
    "preview": "SMA_long = [800, 1000]\nSMA_short = 50\n\nBULL_RSI = 10\nBULL_RSI_high = 80\nBULL_RSI_low = 60\n        \nBEAR_RSI = 15\nBEAR_RS"
  },
  {
    "path": "strategy_parameters/RSI_BULL_BEAR_ADX.toml",
    "chars": 218,
    "preview": "SMA_long = 1000\nSMA_short = 50\n\nBULL_RSI = 10\nBULL_RSI_high = 80\nBULL_RSI_low = 60\n        \nBEAR_RSI = 15\nBEAR_RSI_high "
  },
  {
    "path": "strategy_parameters/RSI_BULL_BEAR_x2.toml",
    "chars": 520,
    "preview": "# MAJOR SMA TRENDS\nMAJOR_SMA_long = 2000\nMAJOR_SMA_short = 500\n\n# MAJOR BULL TREND\n# SMA Trends\nBULL__SMA_long = 1000\nBU"
  },
  {
    "path": "strategy_parameters/WRSI_BULL_BEAR.toml",
    "chars": 187,
    "preview": "SMA_long = 1000\nSMA_short = 50\n\nBULL_RSI = 10\nBULL_RSI_high = 80\nBULL_RSI_low = 60\n        \nBEAR_RSI = 15\nBEAR_RSI_high "
  },
  {
    "path": "strategy_parameters/foxhole.toml",
    "chars": 46,
    "preview": "P0 = [-65.536, 65.536]\nP1 = [-65.536, 65.536]\n"
  },
  {
    "path": "strategy_parameters/griewangk.toml",
    "chars": 170,
    "preview": "P0 = [-600, 600]\nP1 = [-600, 600]\nP2 = [-600, 600]\nP3 = [-600, 600]\nP4 = [-600, 600]\nP5 = [-600, 600]\nP6 = [-600, 600]\nP"
  },
  {
    "path": "strategy_parameters/quartic.toml",
    "chars": 590,
    "preview": "P0 = [-1.28, 1.28]\nP1 = [-1.28, 1.28]\nP2 = [-1.28, 1.28]\nP3 = [-1.28, 1.28]\nP4 = [-1.28, 1.28]\nP5 = [-1.28, 1.28]\nP6 = ["
  },
  {
    "path": "strategy_parameters/rastrigin.toml",
    "chars": 390,
    "preview": "P0 = [-5.12, 5.12]\nP1 = [-5.12, 5.12]\nP2 = [-5.12, 5.12]\nP3 = [-5.12, 5.12]\nP4 = [-5.12, 5.12]\nP5 = [-5.12, 5.12]\nP6 = ["
  },
  {
    "path": "strategy_parameters/rosenbrock.toml",
    "chars": 42,
    "preview": "P0 = [-2.048, 2.048]\nP1 = [-2.048, 2.048]\n"
  },
  {
    "path": "strategy_parameters/scalperNEO.toml",
    "chars": 292,
    "preview": "# SMA Trends\nSMA_long = 150\nSMA_short = 40\n\n# BULL\nBULL_RSI = 10\nBULL_RSI_high = 80\nBULL_RSI_low = 50\n\n# IDLE\nIDLE_RSI ="
  },
  {
    "path": "strategy_parameters/scalperRBBA.toml",
    "chars": 233,
    "preview": "SMA_long = 1000\nSMA_short = 50\n\nBULL_RSI = 10\nBULL_RSI_high = 80\nBULL_RSI_low = 60\n        \nBEAR_RSI = 15\nBEAR_RSI_high "
  },
  {
    "path": "strategy_parameters/schwefel.toml",
    "chars": 170,
    "preview": "P0 = [-500, 500]\nP1 = [-500, 500]\nP2 = [-500, 500]\nP3 = [-500, 500]\nP4 = [-500, 500]\nP5 = [-500, 500]\nP6 = [-500, 500]\nP"
  },
  {
    "path": "utilities/importer.sh",
    "chars": 407,
    "preview": "#!/bin/bash\n\n# To run GAs one needs candlestick datasets to backtest.\n# Grabbing that data on a VPS can be a pain, so th"
  },
  {
    "path": "utilities/poloUSDTBTC.js",
    "chars": 1886,
    "preview": "// Everything is explained here:\n// @link https://gekko.wizb.it/docs/commandline/plugins.html\n\nvar config = {};\n\n// ~~~~"
  },
  {
    "path": "utilities/poloUSDTETH.js",
    "chars": 1887,
    "preview": "// Everything is explained here:\n// @link https://gekko.wizb.it/docs/commandline/plugins.html\n\nvar config = {};\n\n// ~~~~"
  },
  {
    "path": "utilities/poloUSDTLTC.js",
    "chars": 1887,
    "preview": "// Everything is explained here:\n// @link https://gekko.wizb.it/docs/commandline/plugins.html\n\nvar config = {};\n\n// ~~~~"
  },
  {
    "path": "version.py",
    "chars": 29,
    "preview": "#!/bin/python\nVERSION = 0.92\n"
  }
]

About this extraction

This page contains the full source code of the Gab0/japonicus GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 104 files (179.0 KB), approximately 48.0k tokens, and a symbol index with 216 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.

Copied to clipboard!