Full Code of askmike/gekko for AI

develop ff5698f1ae63 cached
371 files
2.1 MB
563.1k tokens
2804 symbols
1 requests
Download .txt
Showing preview only (2,246K chars total). Download the full file or copy to clipboard to get everything.
Repository: askmike/gekko
Branch: develop
Commit: ff5698f1ae63
Files: 371
Total size: 2.1 MB

Directory structure:
gitextract_1c3mqyr_/

├── .dockerignore
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── stale.yml
├── .gitignore
├── .prettierrc
├── .travis.yml
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── appveyor.yml
├── config/
│   ├── adapters/
│   │   ├── mongodb.toml
│   │   ├── postgresql.toml
│   │   └── sqlite.toml
│   ├── backtest.toml
│   ├── general.toml
│   ├── plugins/
│   │   ├── candleWriter.toml
│   │   ├── paperTrader.toml
│   │   ├── performanceAnalyzer.toml
│   │   ├── pushbullet.toml
│   │   ├── trader.toml
│   │   └── tradingAdvisor.toml
│   └── strategies/
│       ├── CCI.toml
│       ├── DEMA.toml
│       ├── MACD.toml
│       ├── PPO.toml
│       ├── RSI.toml
│       ├── StochRSI.toml
│       ├── TMA.toml
│       ├── TSI.toml
│       ├── UO.toml
│       ├── custom.toml
│       ├── talib-macd.toml
│       ├── tulip-adx.toml
│       ├── tulip-macd.toml
│       ├── tulip-multi-strat.toml
│       └── varPPO.toml
├── core/
│   ├── budfox/
│   │   ├── budfox.js
│   │   ├── candleCreator.js
│   │   ├── candleManager.js
│   │   ├── heart.js
│   │   ├── marketDataProvider.js
│   │   ├── marketFetcher.js
│   │   └── tradeBatcher.js
│   ├── candleBatcher.js
│   ├── emitter.js
│   ├── gekkoStream.js
│   ├── log.js
│   ├── markets/
│   │   ├── backtest.js
│   │   ├── importer.js
│   │   ├── leech.js
│   │   └── realtime.js
│   ├── pipeline.js
│   ├── pluginUtil.js
│   ├── prepareDateRange.js
│   ├── stats.js
│   ├── talib.js
│   ├── tools/
│   │   ├── candleLoader.js
│   │   ├── configBuilder.js
│   │   ├── dataStitcher.js
│   │   └── dateRangeScanner.js
│   ├── tulind.js
│   ├── util.js
│   └── workers/
│       ├── datasetScan/
│       │   └── parent.js
│       ├── dateRangeScan/
│       │   ├── child.js
│       │   └── parent.js
│       ├── loadCandles/
│       │   ├── child.js
│       │   └── parent.js
│       └── pipeline/
│           ├── child.js
│           ├── messageHandlers/
│           │   ├── backtestHandler.js
│           │   ├── importerHandler.js
│           │   └── realtimeHandler.js
│           └── parent.js
├── docker-compose.yml
├── docker-entrypoint.sh
├── docs/
│   ├── commandline/
│   │   ├── Importing.md
│   │   ├── about_the_commandline.md
│   │   ├── backtesting.md
│   │   ├── plugins.md
│   │   └── tradebot.md
│   ├── extending/
│   │   ├── add_a_plugin.md
│   │   ├── add_an_exchange.md
│   │   └── other_software.md
│   ├── features/
│   │   ├── backtesting.md
│   │   ├── importing.md
│   │   ├── paper_trading.md
│   │   └── trading_bot.md
│   ├── gekko-broker/
│   │   ├── introduction.md
│   │   ├── sticky_order.md
│   │   └── wrapper_api.md
│   ├── installation/
│   │   ├── configuring_gekko_on_a_server.md
│   │   ├── installing_gekko.md
│   │   ├── installing_gekko_on_raspberry_pi_2_or_3.md
│   │   ├── installing_gekko_on_windows.md
│   │   ├── installing_gekko_on_windows_with_bash_on_windows_10.md
│   │   ├── installing_gekko_using_docker.md
│   │   └── updating_gekko.md
│   ├── internals/
│   │   ├── architecture.md
│   │   ├── budfox.md
│   │   ├── events.md
│   │   ├── gekko_ui.md
│   │   ├── plugins.md
│   │   └── server_api.md
│   ├── introduction/
│   │   ├── about_gekko.md
│   │   ├── getting_help.md
│   │   ├── roadmap.md
│   │   ├── scope.md
│   │   ├── supported_exchanges.md
│   │   └── supporting_the_project.md
│   └── strategies/
│       ├── creating_a_strategy.md
│       ├── gekko_indicators.md
│       ├── introduction.md
│       ├── talib_indicators.md
│       └── tulip_indicators.md
├── exchange/
│   ├── .npmignore
│   ├── README.md
│   ├── dependencyCheck.js
│   ├── exchangeChecker.js
│   ├── exchangeErrors.js
│   ├── exchangeUtils.js
│   ├── gekkoBroker.js
│   ├── orders/
│   │   ├── index.js
│   │   ├── limit.js
│   │   ├── order.js
│   │   ├── states.js
│   │   └── sticky.js
│   ├── package.json
│   ├── portfolioManager.js
│   ├── trigger.js
│   ├── triggers/
│   │   ├── index.js
│   │   └── trailingStop.js
│   ├── util/
│   │   └── genMarketFiles/
│   │       ├── update-binance.js
│   │       ├── update-bitfinex.js
│   │       ├── update-coinbase.js
│   │       ├── update-coinfalcon.js
│   │       └── update-kraken.js
│   └── wrappers/
│       ├── DEBUG_exchange-simulator.js
│       ├── binance-markets.json
│       ├── binance.js
│       ├── bitcoin-co-id.js.old
│       ├── bitfinex-markets.json
│       ├── bitfinex.js
│       ├── bitfinex_v2.js.prep
│       ├── bitstamp.js.old
│       ├── bittrex.js
│       ├── btc-markets.js.old
│       ├── btcc.js.old
│       ├── bx.in.th.js.old
│       ├── cexio.js.old
│       ├── coinbase-markets.json
│       ├── coinfalcon-markets.json
│       ├── coinfalcon.js
│       ├── coingi.js
│       ├── exmo-markets.json
│       ├── exmo.js
│       ├── gdax.js
│       ├── gemini.js.old
│       ├── kraken-markets.json
│       ├── kraken.js
│       ├── lakebtc.js
│       ├── luno.js
│       ├── mexbt.js.old
│       ├── mtgox.js.old
│       ├── okcoin.js.old
│       ├── poloniex-markets.json
│       ├── poloniex.js
│       ├── quadriga-markets.json
│       ├── quadriga.js.old
│       ├── therocktrading-markets.json
│       ├── therocktrading.js
│       ├── wex.nz.js.old
│       └── zaif.jp.js.old
├── gekko.js
├── importers/
│   └── exchanges/
│       ├── binance.js
│       ├── bitfinex.js
│       ├── btcc.js
│       ├── coinfalcon.js
│       ├── gdax.js
│       ├── kraken.js
│       ├── luno.js
│       ├── poloniex.js
│       └── therocktrading.js
├── logs/
│   └── .gitignore
├── package.json
├── plugins/
│   ├── adviceLogger.js
│   ├── backtestResultExporter.js
│   ├── blotter.js
│   ├── campfire.js
│   ├── candleUploader.js
│   ├── childToParent.js
│   ├── eventLogger.js
│   ├── ifttt.js
│   ├── ircbot.js
│   ├── kodi.js
│   ├── mailer.js
│   ├── mongodb/
│   │   ├── handle.js
│   │   ├── reader.js
│   │   ├── scanner.js
│   │   ├── util.js
│   │   └── writer.js
│   ├── paperTrader/
│   │   └── paperTrader.js
│   ├── performanceAnalyzer/
│   │   ├── logger.js
│   │   └── performanceAnalyzer.js
│   ├── postgresql/
│   │   ├── handle.js
│   │   ├── reader.js
│   │   ├── scanner.js
│   │   ├── util.js
│   │   └── writer.js
│   ├── pushbullet.js
│   ├── pushover.js
│   ├── redisBeacon.js
│   ├── slack.js
│   ├── sqlite/
│   │   ├── handle.js
│   │   ├── reader.js
│   │   ├── scanner.js
│   │   ├── util.js
│   │   └── writer.js
│   ├── telegrambot.js
│   ├── trader/
│   │   └── trader.js
│   ├── tradingAdvisor/
│   │   ├── asyncIndicatorRunner.js
│   │   ├── baseTradingMethod.js
│   │   └── tradingAdvisor.js
│   ├── twitter.js
│   ├── webserver.js
│   └── xmppbot.js
├── plugins.js
├── sample-config.js
├── strategies/
│   ├── CCI.js
│   ├── DEBUG_single-advice.js
│   ├── DEBUG_toggle-advice.js
│   ├── DEMA.js
│   ├── MACD.js
│   ├── PPO.js
│   ├── RSI.js
│   ├── StochRSI.js
│   ├── TMA.js
│   ├── TSI.js
│   ├── UO.js
│   ├── custom.js
│   ├── indicators/
│   │   ├── CCI.js
│   │   ├── DEMA.js
│   │   ├── EMA.js
│   │   ├── LRC.js
│   │   ├── MACD.js
│   │   ├── PPO.js
│   │   ├── RSI.js
│   │   ├── SMA.js
│   │   ├── SMMA.js
│   │   ├── TSI.js
│   │   └── UO.js
│   ├── noop.js
│   ├── talib-macd.js
│   ├── tulip-adx.js
│   ├── tulip-macd.js
│   ├── tulip-multi-strat.js
│   └── varPPO.js
├── subscriptions.js
├── test/
│   ├── _prepare.js
│   ├── candleBatcher.js
│   ├── exchanges/
│   │   ├── bitstamp.js
│   │   └── data/
│   │       └── bitstamp_trades.json
│   ├── indicators/
│   │   ├── cci.js
│   │   ├── dema.js
│   │   ├── ema.js
│   │   ├── macd.js
│   │   ├── ppo.js
│   │   ├── rsi.js
│   │   ├── sma.js
│   │   └── smma.js
│   ├── marketFetcher.js
│   ├── plugins/
│   │   └── portfolioManager.js
│   ├── test-config.json
│   ├── tradeBatcher.js
│   └── triggers/
│       └── trailingStop.js
└── web/
    ├── apiKeyManager.js
    ├── baseUIconfig.js
    ├── isWindows.js
    ├── routes/
    │   ├── apiKeys.js
    │   ├── backtest.js
    │   ├── baseConfig.js
    │   ├── configPart.js
    │   ├── deleteGekko.js
    │   ├── exchanges.js
    │   ├── getCandles.js
    │   ├── import.js
    │   ├── info.js
    │   ├── list.js
    │   ├── scanDatasets.js
    │   ├── scanDateRange.js
    │   ├── startGekko.js
    │   ├── stopGekko.js
    │   └── strategies.js
    ├── server.js
    ├── state/
    │   ├── cache.js
    │   ├── gekkoManager.js
    │   ├── listManager.js
    │   ├── logger.js
    │   └── reduceState.js
    └── vue/
        ├── babel.config.js
        ├── dist/
        │   ├── UIconfig.js
        │   ├── app.5e99ecf7.js
        │   ├── app.730569ff.css
        │   ├── chunk-vendors.b9a11975.js
        │   ├── index.html
        │   └── vendor/
        │       ├── d3.js
        │       ├── humanize-duration.js
        │       ├── moment.js
        │       └── toml.js
        ├── package.json
        ├── public/
        │   ├── UIconfig.js
        │   ├── index.html
        │   └── vendor/
        │       ├── d3.js
        │       ├── humanize-duration.js
        │       ├── moment.js
        │       └── toml.js
        ├── src/
        │   ├── App.vue
        │   ├── components/
        │   │   ├── backtester/
        │   │   │   ├── backtestConfigBuilder.vue
        │   │   │   ├── backtester.vue
        │   │   │   └── result/
        │   │   │       ├── chartWrapper.vue
        │   │   │       ├── result.vue
        │   │   │       ├── roundtripTable.vue
        │   │   │       └── summary.vue
        │   │   ├── config/
        │   │   │   ├── apiConfigBuilder.vue
        │   │   │   └── config.vue
        │   │   ├── data/
        │   │   │   ├── data.vue
        │   │   │   └── import/
        │   │   │       ├── importConfigBuilder.vue
        │   │   │       ├── importer.vue
        │   │   │       └── single.vue
        │   │   ├── gekko/
        │   │   │   ├── gekkoConfigBuilder.vue
        │   │   │   ├── list.vue
        │   │   │   ├── new.vue
        │   │   │   ├── singleGekko.vue
        │   │   │   └── singleWatcher.vue
        │   │   ├── global/
        │   │   │   ├── blockSpinner.vue
        │   │   │   ├── configbuilder/
        │   │   │   │   ├── datasetpicker.vue
        │   │   │   │   ├── exchangepicker.vue
        │   │   │   │   ├── marketpicker.vue
        │   │   │   │   ├── papertrader.vue
        │   │   │   │   ├── rangecreator.vue
        │   │   │   │   ├── rangepicker.vue
        │   │   │   │   ├── stratpicker.vue
        │   │   │   │   └── typepicker.vue
        │   │   │   ├── mixins/
        │   │   │   │   └── dataset.js
        │   │   │   ├── paperTradeSummary.vue
        │   │   │   ├── progressBar.vue
        │   │   │   └── ws.js
        │   │   └── layout/
        │   │       ├── footer.vue
        │   │       ├── header.vue
        │   │       ├── home.vue
        │   │       └── modal.vue
        │   ├── d3/
        │   │   ├── chart3.js
        │   │   ├── chart4.js
        │   │   └── message.js
        │   ├── main.js
        │   ├── store/
        │   │   ├── index.js
        │   │   ├── init.js
        │   │   └── modules/
        │   │       ├── config/
        │   │       │   ├── mutations.js
        │   │       │   └── sync.js
        │   │       ├── gekkos/
        │   │       │   ├── mutations.js
        │   │       │   └── sync.js
        │   │       ├── imports/
        │   │       │   ├── mutations.js
        │   │       │   └── sync.js
        │   │       ├── messages/
        │   │       │   └── mutations.js
        │   │       └── notifications/
        │   │           ├── mutations.js
        │   │           └── sync.js
        │   └── tools/
        │       ├── ajax.js
        │       ├── api.js
        │       └── marked.js
        └── vue.config.js

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

================================================
FILE: .dockerignore
================================================
node_modules
.travis.yml
volumes
config.js
sample-config.js
.git
.gitignore

================================================
FILE: .editorconfig
================================================
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
**Note: this is the technical bug tracker, please use other platforms for getting support and starting a (non technical) discussion. See the [getting help page](https://gekko.wizb.it/docs/introduction/getting-help.html) for details.**

**I'm submitting a ...**
[ ] bug report
[ ] question about the decisions made in the repository

**Action taken** (what you did)


**Expected result** (what you hoped would happen)


**Actual result** (unexpected outcome)


**Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc)



================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
* **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)



* **What is the current behavior?** (You can also link to an open issue here)



* **What is the new behavior (if this is a feature change)?**



* **Other information**:


================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
  - pinned
  - security
  - important
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
  This issue has been automatically marked as stale because it has not had
  recent activity. It will be closed if no further activity occurs. Thank you
  for your contributions. If you feel this is very a important issue please
  reach out the maintainer of this project directly via e-mail: gekko at mvr dot me.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

================================================
FILE: .gitignore
================================================
# Numerous always-ignore extensions
*.diff
*.err
*.orig
*.log
*.rej
*.swo
*.swp
*.vi
*~
*.sass-cache

# OS or Editor folders
.DS_Store
Thumbs.db
config.js
api-keys.js
.cache
.project
.settings
.tmproj
nbproject
*.sublime-project
*.sublime-workspace

# Dreamweaver added files
_notes
dwsync.xml

# Komodo
*.komodoproject
.komodotools

# Espresso
*.esproj
*.espressostorage

# Folders & files to ignore

node_modules
candles.csv
cexio.db
history
TMP_*
.idea
volumes
config.js
config-*.js
private-*.js
private-*.toml
SECRET-api-keys.json
exchange/nusadua

================================================
FILE: .prettierrc
================================================
{
  "trailingComma": "es5",
  "singleQuote": true
}

================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
  - "8.11.2"

================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Thanks for (thinking about) contributing to Gekko, all help is wanted!

## Before Submitting an Issue

First, please do a search in [open issues](https://github.com/askmike/gekko/issues/) to see if the issue or feature request has already been filed.

If you find your issue already exists, make relevant comments and add your reaction:

👍 - upvote

👎 - downvote

If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.

### Submitting an issue (bug)

* Be as clear and concise as possible.
* Do not submit more than one bug in a single issue.
* Clearly explain the following:

1. Action taken (what you did)
2. Expected result (what you hoped would happen)
3. Actual result (unexpected outcome)
4. Your setup (any and all relevant technical facts, error messages, logs, etc)

### Feature requests

* First consider if **you** yourself might be able to work on the feature?  If so, check out info on contributing code below.
* If you do not have the skills, then please take the time to clearly think through the request. Is is appropriate for all users of Gekko?  If so, create a new issue containing the following:

1. Write `[request]` as the first item in the title, followed by a short, concise description, eg: `[request] Export data to CSV`.
2. Fill in details explaining your request.  Be as clear and concise as possible and only 1 request at a time.
3. Add mock-ups, etc as needed to clearly demonstrate the idea.

## New Feature and code contributions

- If you want to add an exchange to Gekko, see [this doc](https://gekko.wizb.it/docs/extending/add_an_exchange.html) for all the information you need.
- If you want to Gekko react to anything from the market, you can most likely put this functionality into a plugin. See [this document](https://gekko.wizb.it/docs/internals/plugins.html) for details.
- If you want to create a strategy, please see [this page](https://gekko.wizb.it/docs/strategies/creating_a_strategy.html).
- If you just want to work on Gekko, you can use the open issues with the tag `open-for-pulls` for inspiration.
- If you want to work on the web interface (Gekko UI), please see [this frontend doc](https://gekko.wizb.it/docs/internals/gekko_ui.html) on the Vue.js frontend.

Things to take into consideration when submitting a pull request:

 - Please submit all pull requests (except for hotfixes) to the [develop branch](https://github.com/askmike/gekko/tree/develop).
 - Please keep current code styling in mind.


================================================
FILE: Dockerfile
================================================
FROM node:8

ENV HOST localhost
ENV PORT 3000

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install GYP dependencies globally, will be used to code build other dependencies
RUN npm install -g --production node-gyp && \
    npm cache clean --force

# Install Gekko dependencies
COPY package.json .
RUN npm install --production && \
    npm install --production redis@0.10.0 talib@1.0.2 tulind@0.8.7 pg && \
    npm cache clean --force

# Install Gekko Broker dependencies
WORKDIR exchange
COPY exchange/package.json .
RUN npm install --production && \
    npm cache clean --force
WORKDIR ../

# Bundle app source
COPY . /usr/src/app

EXPOSE 3000
RUN chmod +x /usr/src/app/docker-entrypoint.sh
ENTRYPOINT ["/usr/src/app/docker-entrypoint.sh"]

CMD ["--config", "config.js", "--ui"]


================================================
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
================================================
# This repo is not maintained anymore

I am officially not maintaining this project anymore. It was an amazing journey and I want to thank everyone for
playing the role in this amazing story!

More details can be found here: [https://medium.com/@gekkoplus/archiving-open-source-gekko-dba02e6efc7](https://medium.com/@gekkoplus/archiving-open-source-gekko-dba02e6efc7)

This only impacts my Gekko repo (askmike/gekko). There might be other forks of Gekko out there that are being maintained!

------

Old content:

------


# Gekko [![npm](https://img.shields.io/npm/dm/gekko.svg)]() [![Build Status](https://travis-ci.org/askmike/gekko.png)](https://travis-ci.org/askmike/gekko) [![Build status](https://ci.appveyor.com/api/projects/status/github/askmike/gekko?branch=stable&svg=true)](https://ci.appveyor.com/project/askmike/gekko)

![Gordon Gekko](http://mikevanrossum.nl/static/gekko.jpg)

*The most valuable commodity I know of is information.*

-Gordon Gekko

Gekko is a Bitcoin TA trading and backtesting platform that connects to popular Bitcoin exchanges. It is written in JavaScript and runs on [Node.js](http://nodejs.org).

*Use Gekko at your own risk.*

## Documentation

See [the documentation website](https://gekko.wizb.it/docs/introduction/about_gekko.html).

## Installation & Usage

See [the installing Gekko doc](https://gekko.wizb.it/docs/installation/installing_gekko.html).

## Community & Support

Gekko has [a forum](https://forum.gekko.wizb.it/) that is the place for discussions on using Gekko, automated trading and exchanges. In case you rather want to chat in realtime about Gekko feel free to join the [Gekko Support Discord](https://discord.gg/26wMygt).

## Final

If Gekko helped you in any way, you can always leave me a tip at (BTC) 13r1jyivitShUiv9FJvjLH7Nh1ZZptumwW


================================================
FILE: appveyor.yml
================================================
init:
  - git config --global core.autocrlf input

environment:
  nodejs_version: "9"

install:
  - ps: Install-Product node $env:nodejs_version
  - npm install
test_script:
  - node --version
  - npm --version
  - cmd: npm test

build: off

================================================
FILE: config/adapters/mongodb.toml
================================================
connectionString = "mongodb://mongodb/gekko"
path = "plugins/mongodb"
version = 0.1

[[dependencies]]
module = "mongojs"
version = "2.4.0"

================================================
FILE: config/adapters/postgresql.toml
================================================
connectionString = "postgres://user:pass@localhost:5432"
path = "plugins/postgresql"
version = 0.1

[[dependencies]]
module = "pg"
version = "6.1.0"

================================================
FILE: config/adapters/sqlite.toml
================================================
dataDirectory = "history"
path = "plugins/sqlite"
version = 0.1

[[dependencies]]
module = "sqlite3"
version = "3.1.4"

================================================
FILE: config/backtest.toml
================================================
batchSize = 50

# scan for available dateranges
daterange = "scan"
# or specify it like so:
# [daterange]
# from = "2015-01-01"
# to = "2016-01-01"

================================================
FILE: config/general.toml
================================================
debug = true

# what database should Gekko use?
adapter = 'sqlite'

[watch]
exchange = 'Poloniex'
currency = 'USDT'
asset = 'BTC'



================================================
FILE: config/plugins/candleWriter.toml
================================================
enabled = true
adapter = "sqlite"

================================================
FILE: config/plugins/paperTrader.toml
================================================
feeMaker = 0.25
feeTaker = 0.25
feeUsing = 'maker'
slippage = 0.05

[simulationBalance]
asset = 1
currency = 100


================================================
FILE: config/plugins/performanceAnalyzer.toml
================================================
# Used to calculate sharpe ratio
# yearly % of riskfree return for example
# treasury bonds or bank interest.

riskFreeReturn = 2

================================================
FILE: config/plugins/pushbullet.toml
================================================
enabled = false

# Send 'Gekko starting' message if true
sendMessageOnStart = true

# disable advice printout if it's soft
muteSoft = true

# your email, change it unless you are Azor Ahai
email = "jon_snow@westeros.org"

# your pushbullet API key
key = "xxx"

# will make Gekko messages start with [GEKKO]
tag = "[GEKKO]"

================================================
FILE: config/plugins/trader.toml
================================================
enabled = false

## NOTE: once you filled in the following
## never share this file with anyone!

key = ""
secret = ""
# this is only required at specific exchanges
username = ""

================================================
FILE: config/plugins/tradingAdvisor.toml
================================================
enabled = true

candleSize = 60
historySize = 25
method = "MACD"

[talib]
enabled = false
version = "1.0.2"

================================================
FILE: config/strategies/CCI.toml
================================================
# constant multiplier. 0.015 gets to around 70% fit
constant = 0.015

# history size, make same or smaller than history
history = 90

[thresholds]
up = 100
down = -100
persistence = 0

================================================
FILE: config/strategies/DEMA.toml
================================================
weight = 21

[thresholds]
down = -0.025
up = 0.025


================================================
FILE: config/strategies/MACD.toml
================================================
short = 10
long = 21
signal = 9

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

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

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

================================================
FILE: config/strategies/RSI.toml
================================================
interval = 14

[thresholds]
low = 30
high = 70
persistence = 1

================================================
FILE: config/strategies/StochRSI.toml
================================================
interval = 3

[thresholds]
low = 20
high = 80
persistence = 3

================================================
FILE: config/strategies/TMA.toml
================================================
short = 7
medium = 25
long = 99


================================================
FILE: config/strategies/TSI.toml
================================================
short = 13
long = 25

[thresholds]
low = -25
high = 25
persistence = 1

================================================
FILE: config/strategies/UO.toml
================================================
[first]
weight = 4
period = 7

[second]
weight = 2
period = 14

[third]
weight = 1
period = 28

[thresholds]
low = 30
high = 70
persistence = 1


================================================
FILE: config/strategies/custom.toml
================================================
my_custom_setting = 10

================================================
FILE: config/strategies/talib-macd.toml
================================================
[parameters]
optInFastPeriod = 10
optInSlowPeriod = 21
optInSignalPeriod = 9

[thresholds]
down = -0.025
up = 0.025

================================================
FILE: config/strategies/tulip-adx.toml
================================================
historySize = 80
optInTimePeriod = 15
candleSize = 10

[thresholds]
up = 30
down = 20

================================================
FILE: config/strategies/tulip-macd.toml
================================================
[parameters]
optInFastPeriod = 10
optInSlowPeriod = 21
optInSignalPeriod = 9

[thresholds]
down = -0.025
up = 0.025

================================================
FILE: config/strategies/tulip-multi-strat.toml
================================================
optInTimePeriod = 2
optInFastPeriod = 4
optInSlowPeriod = 7
optInSignalPeriod = 23.707189677282354

candleSize = 1
historySize = 4

up = 24.52
down = 55.74
macd_up = 14.498233170768081
macd_down = -9.65220944122072


================================================
FILE: config/strategies/varPPO.toml
================================================
momentum = "TSI" # RSI, TSI or UO

[thresholds]
weightLow = 120
weightHigh = -120

# How many candle intervals should a trend persist
# before we consider it real?
persistence = 0

================================================
FILE: core/budfox/budfox.js
================================================
// Budfox is the realtime market for Gekko!
//
// Read more here:
// @link https://github.com/askmike/gekko/blob/stable/docs/internals/budfox.md
//
// > [getting up] I don't know. I guess I realized that I'm just Bud Fox.
// > As much as I wanted to be Gordon Gekko, I'll *always* be Bud Fox.
// > [tosses back the handkerchief and walks away]

var _ = require('lodash');
var async = require('async');

var util = require(__dirname + '/../util');
var dirs = util.dirs();

var Heart = require(dirs.budfox + 'heart');
var MarketDataProvider =  require(dirs.budfox + 'marketDataProvider');
var CandleManager = require(dirs.budfox + 'candleManager');

var BudFox = function(config) {
  _.bindAll(this);

  Readable.call(this, {objectMode: true});

  // BudFox internal modules:
  
  this.heart = new Heart;
  this.marketDataProvider = new MarketDataProvider(config);
  this.candleManager = new CandleManager;

  //    BudFox data flow:

  // relay a marketUpdate event
  this.marketDataProvider.on(
    'marketUpdate',
    e => this.emit('marketUpdate', e)
  );

  // relay a marketStart event
  this.marketDataProvider.on(
    'marketStart',
    e => this.emit('marketStart', e)
  );

  // Output the candles
  this.candleManager.on(
    'candles',
    this.pushCandles
  );

  // on every `tick` retrieve trade data
  this.heart.on(
    'tick',
    this.marketDataProvider.retrieve
  );

  // on new trade data create candles
  this.marketDataProvider.on(
    'trades',
    this.candleManager.processTrades
  );

  this.heart.pump();
}

var Readable = require('stream').Readable;

BudFox.prototype = Object.create(Readable.prototype, {
  constructor: { value: BudFox }
});

BudFox.prototype._read = function noop() {}

BudFox.prototype.pushCandles = function(candles) {
  _.each(candles, this.push);
}

module.exports = BudFox;


================================================
FILE: core/budfox/candleCreator.js
================================================
// The CandleCreator creates one minute candles based on trade batches. Note
// that it also adds empty candles to fill gaps with no volume.
//
// Expects trade batches to be written like:
//
// {
//   amount: x,
//   start: (moment),
//   end: (moment),
//   first: (trade),
//   last: (trade),
//   timespan: x,
//   all: [
//      // batch of new trades with
//      // moments instead of timestamps
//   ]
// }
//
// Emits 'new candles' event with:
//
// [
//     {
//       start: (moment),
//       end: (moment),
//       high: (float),
//       open: (float),
//       low: (float),
//       close: (float)
//       volume: (float)
//       vwp: (float) // volume weighted price
//    },
//    {
//       start: (moment), // + 1
//       end: (moment),
//       high: (float),
//       open: (float),
//      low: (float),
//      close: (float)
//       volume: (float)
//       vwp: (float) // volume weighted price
//    }
//    // etc.
// ]
//

var _ = require('lodash');
var moment = require('moment');

var util = require(__dirname + '/../util');

var CandleCreator = function() {
  _.bindAll(this);

  // TODO: remove fixed date
  this.threshold = moment("1970-01-01", "YYYY-MM-DD");

  // This also holds the leftover between fetches
  this.buckets = {};
}

util.makeEventEmitter(CandleCreator);

CandleCreator.prototype.write = function(batch) {
  var trades = batch.data;

  if(_.isEmpty(trades))
    return;

  trades = this.filter(trades);
  this.fillBuckets(trades);
  var candles = this.calculateCandles();

  candles = this.addEmptyCandles(candles);

  if(_.isEmpty(candles))
    return;  

  // the last candle is not complete
  this.threshold = candles.pop().start;

  this.emit('candles', candles);
}

CandleCreator.prototype.filter = function(trades) {
  // make sure we only include trades more recent
  // than the previous emitted candle
  return _.filter(trades, function(trade) {
    return trade.date > this.threshold;
  }, this);
}

// put each trade in a per minute bucket
CandleCreator.prototype.fillBuckets = function(trades) {
  _.each(trades, function(trade) {
    var minute = trade.date.format('YYYY-MM-DD HH:mm');

    if(!(minute in this.buckets))
      this.buckets[minute] = [];

    this.buckets[minute].push(trade);
  }, this);

  this.lastTrade = _.last(trades);
}

// convert each bucket into a candle
CandleCreator.prototype.calculateCandles = function() {
  var minutes = _.size(this.buckets);

  // catch error from high volume getTrades
  if (this.lastTrade !== undefined)
    // create a string referencing the minute this trade happened in
    var lastMinute = this.lastTrade.date.format('YYYY-MM-DD HH:mm');

  var candles = _.map(this.buckets, function(bucket, name) {
    var candle = this.calculateCandle(bucket);

    // clean all buckets, except the last one:
    // this candle is not complete
    if(name !== lastMinute)
      delete this.buckets[name];

    return candle;
  }, this);

  return candles;
}

CandleCreator.prototype.calculateCandle = function(trades) {
  var first = _.first(trades);

  var f = parseFloat;

  var candle = {
    start: first.date.clone().startOf('minute'),
    open: f(first.price),
    high: f(first.price),
    low: f(first.price),
    close: f(_.last(trades).price),
    vwp: 0,
    volume: 0,
    trades: _.size(trades)
  };

  _.each(trades, function(trade) {
    candle.high = _.max([candle.high, f(trade.price)]);
    candle.low = _.min([candle.low, f(trade.price)]);
    candle.volume += f(trade.amount);
    candle.vwp += f(trade.price) * f(trade.amount);
  });

  candle.vwp /= candle.volume;

  return candle;
}

// Gekko expects a candle every minute, if nothing happened
// during a particilar minute Gekko will add empty candles with:
//
// - open, high, close, low, vwp are the same as the close of the previous candle.
// - trades, volume are 0
CandleCreator.prototype.addEmptyCandles = function(candles) {
  var amount = _.size(candles);
  if(!amount)
    return candles;

  // iterator
  var start = _.first(candles).start.clone();
  var end = _.last(candles).start;
  var i, j = -1;

  var minutes = _.map(candles, function(candle) {
    return +candle.start;
  });

  while(start < end) {
    start.add(1, 'm');
    i = +start;
    j++;

    if(_.contains(minutes, i))
      continue; // we have a candle for this minute

    var lastPrice = candles[j].close;

    candles.splice(j + 1, 0, {
      start: start.clone(),
      open: lastPrice,
      high: lastPrice,
      low: lastPrice,
      close: lastPrice,
      vwp: lastPrice,
      volume: 0,
      trades: 0
    });
  }
  return candles;
}

module.exports = CandleCreator;


================================================
FILE: core/budfox/candleManager.js
================================================
// The candleManager consumes trades and emits:
// - `candles`: array of minutly candles.
// - `candle`: the most recent candle after a fetch Gekko.

var _ = require('lodash');
var moment = require('moment');
var fs = require('fs');

var util = require(__dirname + '/../util');
var dirs = util.dirs();
var config = util.getConfig();
var log = require(dirs.core + 'log');

var CandleCreator = require(dirs.budfox + 'candleCreator');

var Manager = function() {
  _.bindAll(this);

  this.candleCreator = new CandleCreator;

  this.candleCreator
    .on('candles', this.relayCandles);
};

util.makeEventEmitter(Manager);
Manager.prototype.processTrades = function(tradeBatch) {
  this.candleCreator.write(tradeBatch);
}

Manager.prototype.relayCandles = function(candles) {
  this.emit('candles', candles);
}

module.exports = Manager;


================================================
FILE: core/budfox/heart.js
================================================
// The heart schedules and emit ticks every 20 seconds.

var util = require(__dirname + '/../util');
var log = require(util.dirs().core + 'log');

var _ = require('lodash');
var moment = require('moment');

if (util.getConfig().watch.tickrate)
  var TICKRATE = util.getConfig().watch.tickrate;
else if(util.getConfig().watch.exchange === 'okcoin')
  var TICKRATE = 2;
else
  var TICKRATE = 20;

var Heart = function() {
  this.lastTick = false;

  _.bindAll(this);
}

util.makeEventEmitter(Heart);

Heart.prototype.pump = function() {
  log.debug('scheduling ticks');
  this.scheduleTicks();
}

Heart.prototype.tick = function() {
  if(this.lastTick) {
    // make sure the last tick happened not to lang ago
    // @link https://github.com/askmike/gekko/issues/514
    if(this.lastTick < moment().unix() - TICKRATE * 3)
      util.die('Failed to tick in time, see https://github.com/askmike/gekko/issues/514 for details', true);
  }

  this.lastTick = moment().unix();
  this.emit('tick');
}

Heart.prototype.scheduleTicks = function() {
  setInterval(
    this.tick,
    +moment.duration(TICKRATE, 's')
  );

  // start!
  _.defer(this.tick);
}

module.exports = Heart;


================================================
FILE: core/budfox/marketDataProvider.js
================================================
// 
// The market data provider will fetch data from a datasource on tick. It emits:
// 
// - `trades`: batch of newly detected trades
// - `trade`: after Gekko fetched new trades, this
//   will be the most recent one.

const _ = require('lodash');
const util = require(__dirname + '/../util');

const MarketFetcher = require('./marketFetcher');
const dirs = util.dirs();

const Manager = function(config) {

  _.bindAll(this);

  // fetch trades
  this.source = new MarketFetcher(config);

  // relay newly fetched trades
  this.source
    .on('trades batch', this.relayTrades);
}

util.makeEventEmitter(Manager);

// HANDLERS
Manager.prototype.retrieve = function() {
  this.source.fetch();
}


Manager.prototype.relayTrades = function(batch) {
  this.sendMarketStart(batch);
  this.emit('marketUpdate', batch.last.date);

  this.emit('trades', batch);
}

Manager.prototype.sendMarketStart = _.once(function(batch) {
  this.emit('marketStart', batch.first.date);
});

module.exports = Manager;

================================================
FILE: core/budfox/marketFetcher.js
================================================
//
// The fetcher is responsible for fetching new
// market data at the exchange on interval. It will emit
// the following events:
//
// - `trades batch` - all new trades.
// - `trade` - the most recent trade after every fetch

const _ = require('lodash');
const moment = require('moment');
const utc = moment.utc;
const util = require(__dirname + '/../util');
const dirs = util.dirs();

const config = util.getConfig();
const log = require(dirs.core + 'log');
const exchangeChecker = require(dirs.gekko + 'exchange/exchangeChecker');

const TradeBatcher = require(util.dirs().budfox + 'tradeBatcher');

const Fetcher = function(config) {
  if(!_.isObject(config))
    throw new Error('TradeFetcher expects a config');

  const exchangeName = config.watch.exchange.toLowerCase();
  const DataProvider = require(util.dirs().gekko + 'exchange/wrappers/' + exchangeName);
  _.bindAll(this);

  // Create a public dataProvider object which can retrieve live
  // trade information from an exchange.
  this.exchangeTrader = new DataProvider(config.watch);

  this.exchange = exchangeChecker.settings(config.watch);

  var requiredHistory = config.tradingAdvisor.candleSize * config.tradingAdvisor.historySize;

  // If the trading adviser is enabled we might need a very specific fetch since
  // to line up [local db, trading method, and fetching]
  if(config.tradingAdvisor.enabled && config.tradingAdvisor.firstFetchSince) {
    this.firstSince = config.tradingAdvisor.firstFetchSince;

    if(this.exchange.providesHistory === 'date') {
      this.firstSince = moment.unix(this.firstSince).utc();
    }
  }

  this.batcher = new TradeBatcher(this.exchange.tid);

  this.pair = [
    config.watch.asset,
    config.watch.currency
  ].join('/');

  log.info('Starting to watch the market:',
    this.exchange.name,
    this.pair
  );

  // if the exchange returns an error
  // we will keep on retrying until next
  // scheduled fetch.
  this.tries = 0;
  this.limit = 20; // [TODO]

  this.firstFetch = true;

  this.batcher.on('new batch', this.relayTrades);
}

util.makeEventEmitter(Fetcher);

Fetcher.prototype._fetch = function(since) {
  if(++this.tries >= this.limit)
    return;

  this.exchangeTrader.getTrades(since, this.processTrades, false);
}

Fetcher.prototype.fetch = function() {
  var since = false;
  if(this.firstFetch) {
    since = this.firstSince;
    this.firstFetch = false;
  } else
    since = false;

  this.tries = 0;
  log.debug('Requested', this.pair, 'trade data from', this.exchange.name, '...');
  this._fetch(since);
}

Fetcher.prototype.processTrades = function(err, trades) {
  if(err || _.isEmpty(trades)) {
    if(err) {
      log.warn(this.exchange.name, 'returned an error while fetching trades:', err);
      log.debug('refetching...');
    } else
      log.debug('Trade fetch came back empty, refetching...');
    setTimeout(this._fetch, +moment.duration('s', 1));
    return;
  }
  this.batcher.write(trades);
}

Fetcher.prototype.relayTrades = function(batch) {
  this.emit('trades batch', batch);
}

module.exports = Fetcher;


================================================
FILE: core/budfox/tradeBatcher.js
================================================
// 
// Small wrapper that only propagates new trades.
// 
// Expects trade batches to be written like:
// [
//  {
//    tid: x, // tid is preferred, but if none available date will also work
//    price: x,
//    date: (timestamp),
//    amount: x
//  },
//  {
//    tid: x + 1,
//    price: x,
//    date: (timestamp),
//    amount: x
//  }
// ]
// 
// Emits 'new trades' event with:
// {
//   amount: x,
//   start: (moment),
//   end: (moment),
//   first: (trade),
//   last: (trade)
//   data: [
//      // batch of new trades with 
//      // moments instead of timestamps
//   ]
// }

var _ = require('lodash');
var moment = require('moment');
var util = require('../util');
var log = require('../log');

var TradeBatcher = function(tid) {
  if(!_.isString(tid))
    throw new Error('tid is not a string');

  _.bindAll(this);
  this.tid = tid;
  this.last = -1;
}

util.makeEventEmitter(TradeBatcher);

TradeBatcher.prototype.write = function(batch) {

  if(!_.isArray(batch))
    throw new Error('batch is not an array');

  if(_.isEmpty(batch))
    return log.debug('Trade fetch came back empty.');

  var filterBatch = this.filter(batch);

  var amount = _.size(filterBatch);
  if(!amount)
    return log.debug('No new trades.');

  var momentBatch = this.convertDates(filterBatch);

  var last = _.last(momentBatch);
  var first = _.first(momentBatch);

  log.debug(
    'Processing', amount, 'new trades.',
    'From',
    first.date.format('YYYY-MM-DD HH:mm:ss'),
    'UTC to',
    last.date.format('YYYY-MM-DD HH:mm:ss'),
    'UTC.',
    '(' + first.date.from(last.date, true) + ')'
  );

  this.emit('new batch', {
    amount: amount,
    start: first.date,
    end: last.date,
    last: last,
    first: first,
    data: momentBatch
  });

  this.last = last[this.tid];

  // we overwrote those, get unix ts back
  if(this.tid === 'date')
    this.last = this.last.unix();

}

TradeBatcher.prototype.filter = function(batch) {
  // make sure we're not trying to count
  // beyond infinity
  var lastTid = _.last(batch)[this.tid];
  if(lastTid === lastTid + 1)
    util.die('trade tid is max int, Gekko can\'t process..');

  // remove trades that have zero amount
  // see @link
  // https://github.com/askmike/gekko/issues/486
  batch = _.filter(batch, function(trade) {
    return trade.amount > 0;
  });

  // weed out known trades
  // TODO: optimize by stopping as soon as the
  // first trade is too old (reverse first)
  return _.filter(batch, function(trade) {
    return this.last < trade[this.tid];
  }, this);
}

TradeBatcher.prototype.convertDates = function(batch) {
  return _.map(_.cloneDeep(batch), function(trade) {
    trade.date = moment.unix(trade.date).utc();
    return trade;
  });
}

module.exports = TradeBatcher;


================================================
FILE: core/candleBatcher.js
================================================
// internally we only use 1m
// candles, this can easily
// convert them to any desired
// size.

// Acts as ~fake~ stream: takes
// 1m candles as input and emits
// bigger candles.
// 
// input are transported candles.

var _ = require('lodash');
var util = require(__dirname + '/util');

var CandleBatcher = function(candleSize) {
  if(!_.isNumber(candleSize))
    throw new Error('candleSize is not a number');

  this.candleSize = candleSize;
  this.smallCandles = [];
  this.calculatedCandles = [];

  _.bindAll(this);
}

util.makeEventEmitter(CandleBatcher);

CandleBatcher.prototype.write = function(candles) {
  if(!_.isArray(candles)) {
    throw new Error('candles is not an array');
  }

  this.emitted = 0;

  _.each(candles, function(candle) {
    this.smallCandles.push(candle);
    this.check();
  }, this);

  return this.emitted;
}

CandleBatcher.prototype.check = function() {
  if(_.size(this.smallCandles) % this.candleSize !== 0)
    return;

  this.emitted++;
  this.calculatedCandles.push(this.calculate());
  this.smallCandles = [];
}

CandleBatcher.prototype.flush = function() {
  _.each(
    this.calculatedCandles,
    candle => this.emit('candle', candle)
  );

  this.calculatedCandles = [];
}

CandleBatcher.prototype.calculate = function() {
  // remove the id property of the small candle
  var { id, ...first } = this.smallCandles.shift();

  first.vwp = first.vwp * first.volume;

  var candle = _.reduce(
    this.smallCandles,
    function(candle, m) {
      candle.high = _.max([candle.high, m.high]);
      candle.low = _.min([candle.low, m.low]);
      candle.close = m.close;
      candle.volume += m.volume;
      candle.vwp += m.vwp * m.volume;
      candle.trades += m.trades;
      return candle;
    },
    first
  );

  if(candle.volume)
    // we have added up all prices (relative to volume)
    // now divide by volume to get the Volume Weighted Price
    candle.vwp /= candle.volume;
  else
    // empty candle
    candle.vwp = candle.open;

  candle.start = first.start;
  return candle;
}

module.exports = CandleBatcher;


================================================
FILE: core/emitter.js
================================================
// Gekko uses a custom event emitter within the GekkoStream (the plugins) to guarantee
// the correct order of events that are triggered by eachother. Turns sync events from
// LIFO into a FIFO stack based model.
//
// More details here: https://forum.gekko.wizb.it/thread-56579.html

const util = require('util');
const events = require('events');
const NativeEventEmitter = events.EventEmitter;

const GekkoEventEmitter = function() {
  NativeEventEmitter.call(this);
  this.defferedEvents = [];
}

util.inherits(GekkoEventEmitter, NativeEventEmitter);

// push to stack
GekkoEventEmitter.prototype.deferredEmit = function(name, payload) {
  this.defferedEvents.push({name, payload});
}

// resolve FIFO
GekkoEventEmitter.prototype.broadcastDeferredEmit = function() {
  if(this.defferedEvents.length === 0)
    return false;

  const event = this.defferedEvents.shift();

  this.emit(event.name, event.payload);
  return true;
}

module.exports = GekkoEventEmitter;

================================================
FILE: core/gekkoStream.js
================================================
// Small writable stream wrapper that
// passes data to all `candleConsumers`.

const Writable = require('stream').Writable;
const _ = require('lodash');
const async = require('async');
const moment = require('moment');

const util = require('./util');
const env = util.gekkoEnv();
const mode = util.gekkoMode();
const config = util.getConfig();
const log = require(util.dirs().core + 'log');

var Gekko = function(plugins) {
  this.plugins = plugins;
  this.candleConsumers = plugins
    .filter(plugin => plugin.processCandle);
  Writable.call(this, {objectMode: true});

  this.producers = this.plugins
    .filter(p => p.meta.emits);

  this.finalize = _.bind(this.finalize, this);
}

Gekko.prototype = Object.create(Writable.prototype, {
  constructor: { value: Gekko }
});

if(config.debug && mode !== 'importer') {
  // decorate with more debug information
  Gekko.prototype._write = function(chunk, encoding, _done) {

    if(chunk.isFinished) {
      return this.finalize();
    }

    const start = moment();
    var relayed = false;
    var at = null;

    const timer = setTimeout(() => {
      if(!relayed)
        log.error([
          `The plugin "${at}" has not processed a candle for 1 second.`,
          `This will cause Gekko to slow down or stop working completely.`
        ].join(' '));
    }, 1000);

    const flushEvents = _.after(this.candleConsumers.length, () => {
      relayed = true;
      clearInterval(timer);
      this.flushDefferedEvents();
      _done();
    });
    _.each(this.candleConsumers, function(c) {
      at = c.meta.name;
      c.processCandle(chunk, flushEvents);
    }, this);
  }
} else {
  // skip decoration
  Gekko.prototype._write = function(chunk, encoding, _done) {
    if(chunk.isFinished) {
      return this.finalize();
    }

    const flushEvents = _.after(this.candleConsumers.length, () => {
      this.flushDefferedEvents();
      _done();
    });
    _.each(this.candleConsumers, function(c) {
      c.processCandle(chunk, flushEvents);
    }, this);
  }
}

Gekko.prototype.flushDefferedEvents = function() {
  const broadcasted = _.find(
    this.producers,
    producer => producer.broadcastDeferredEmit()
  );

  // If we braodcasted anything we might have
  // triggered more events, recurse until we
  // have fully broadcasted everything.
  if(broadcasted)
    this.flushDefferedEvents();
}

Gekko.prototype.finalize = function() {
  var tradingMethod = _.find(
    this.candleConsumers,
    c => c.meta.name === 'Trading Advisor'
  );

  if(!tradingMethod)
    return this.shutdown();

  tradingMethod.finish(this.shutdown.bind(this));
}

Gekko.prototype.shutdown = function() {
  this.end();
  async.eachSeries(
    this.plugins,
    function(c, callback) {
      if (c.finalize) c.finalize(callback);
      else callback();
    },
    () => {
      // If we are a child process, we signal to the parent to kill the child once it is done
      // so that is has time to process all remaining events (and send report data)
      if (env === 'child-process') process.send('done');
      else process.exit(0);
    }
  );
};

module.exports = Gekko;

================================================
FILE: core/log.js
================================================
/*

  Lightweight logger, print everything that is send to error, warn
  and messages to stdout (the terminal). If config.debug is set in config
  also print out everything send to debug.

*/

var moment = require('moment');
var fmt = require('util').format;
var _ = require('lodash');
var util = require('./util');
var config = util.getConfig();
var debug = config.debug;
var silent = config.silent;

var sendToParent = function() {
  var send = method => (...args) => {
    process.send({log: method, message: args.join(' ')});
  }

  return {
    error: send('error'),
    warn: send('warn'),
    info: send('info'),
    write: send('write')
  }
}

var Log = function() {
  _.bindAll(this);
  this.env = util.gekkoEnv();

  if(this.env === 'standalone')
    this.output = console;
  else if(this.env === 'child-process')
    this.output = sendToParent();
};

Log.prototype = {
  _write: function(method, args, name) {
    if(!name)
      name = method.toUpperCase();

    var message = moment().format('YYYY-MM-DD HH:mm:ss');
    message += ' (' + name + '):\t';
    message += fmt.apply(null, args);

    this.output[method](message);
  },
  error: function() {
    this._write('error', arguments);
  },
  warn: function() {
    this._write('warn', arguments);
  },
  info: function() {
    this._write('info', arguments);
  },
  write: function() {
    var args = _.toArray(arguments);
    var message = fmt.apply(null, args);
    this.output.info(message);
  }
}

if(debug)
  Log.prototype.debug = function() {
    this._write('info', arguments, 'DEBUG');  
  }
else
  Log.prototype.debug = _.noop;

if(silent) {
  Log.prototype.debug = _.noop;
  Log.prototype.info = _.noop;
  Log.prototype.warn = _.noop;
  Log.prototype.write = _.noop;
}

module.exports = new Log;

================================================
FILE: core/markets/backtest.js
================================================
var _ = require('lodash');
var util = require('../util');
var config = util.getConfig();
var dirs = util.dirs();
var log = require(dirs.core + 'log');
var moment = require('moment');

var adapter = config[config.adapter];
var Reader = require(dirs.gekko + adapter.path + '/reader');
var daterange = config.backtest.daterange;

var to = moment.utc(daterange.to);
var from = moment.utc(daterange.from);

if(to <= from)
  util.die('This daterange does not make sense.')

if(!from.isValid())
  util.die('invalid `from`');

if(!to.isValid())
  util.die('invalid `to`');

var Market = function() {

  _.bindAll(this);
  this.pushing = false;
  this.ended = false;
  this.closed = false;

  Readable.call(this, {objectMode: true});

  log.write('');
  log.info('\tWARNING: BACKTESTING FEATURE NEEDS PROPER TESTING');
  log.info('\tWARNING: ACT ON THESE NUMBERS AT YOUR OWN RISK!');
  log.write('');

  this.reader = new Reader();
  this.batchSize = config.backtest.batchSize;
  this.iterator = {
    from: from.clone(),
    to: from.clone().add(this.batchSize, 'm').subtract(1, 's')
  }
}

var Readable = require('stream').Readable;
Market.prototype = Object.create(Readable.prototype, {
  constructor: { value: Market }
});

Market.prototype._read = _.once(function() {
  this.get();
});

Market.prototype.get = function() {
  if(this.iterator.to >= to) {
    this.iterator.to = to;
    this.ended = true;
  }

  this.reader.get(
    this.iterator.from.unix(),
    this.iterator.to.unix(),
    'full',
    this.processCandles
  )
}

Market.prototype.processCandles = function(err, candles) {
  this.pushing = true;
  var amount = _.size(candles);

  if(amount === 0) {
    if(this.ended) {
      this.closed = true;
      this.reader.close();
      this.push({isFinished: true});
    } else {
      util.die('Query returned no candles (do you have local data for the specified range?)');
    }
  }

  if(!this.ended && amount < this.batchSize) {
    var d = function(ts) {
      return moment.unix(ts).utc().format('YYYY-MM-DD HH:mm:ss');
    }
    var from = d(_.first(candles).start);
    var to = d(_.last(candles).start);
    log.warn(`Simulation based on incomplete market data (${this.batchSize - amount} missing between ${from} and ${to}).`);
  }

  _.each(candles, function(c, i) {
    c.start = moment.unix(c.start);
    this.push(c);
  }, this);

  this.pushing = false;

  this.iterator = {
    from: this.iterator.from.clone().add(this.batchSize, 'm'),
    to: this.iterator.from.clone().add(this.batchSize * 2, 'm').subtract(1, 's')
  }

  if(!this.closed)
    this.get();
}

module.exports = Market;


================================================
FILE: core/markets/importer.js
================================================
var _ = require('lodash');
var util = require('../util');
var config = util.getConfig();
var dirs = util.dirs();
var log = require(dirs.core + 'log');
var moment = require('moment');
var gekkoEnv = util.gekkoEnv();

var adapter = config[config.adapter];
var daterange = config.importer.daterange;

var from = moment.utc(daterange.from);

if(daterange.to) {
  var to = moment.utc(daterange.to);
} else {
  var to = moment().utc();
  log.debug(
    'No end date specified for importing, setting to',
    to.format()
  );
}
log.debug(to.format());

if(!from.isValid())
  util.die('invalid `from`');

if(!to.isValid())
  util.die('invalid `to`');

var TradeBatcher = require(dirs.budfox + 'tradeBatcher');
var CandleManager = require(dirs.budfox + 'candleManager');
var exchangeChecker = require(dirs.gekko + 'exchange/exchangeChecker');

var error = exchangeChecker.cantFetchFullHistory(config.watch);
if(error)
  util.die(error, true);

var fetcher = require(dirs.importers + config.watch.exchange);

if(to <= from)
  util.die('This daterange does not make sense.')

var Market = function() {
  _.bindAll(this);
  this.exchangeSettings = exchangeChecker.settings(config.watch);

  this.tradeBatcher = new TradeBatcher(this.exchangeSettings.tid);
  this.candleManager = new CandleManager;
  this.fetcher = fetcher({
    to: to,
    from: from
  });

  this.done = false;

  this.fetcher.bus.on(
    'trades',
    this.processTrades
  );

  this.fetcher.bus.on(
    'done',
    function() {
      this.done = true;
    }.bind(this)
  )

  this.tradeBatcher.on(
    'new batch',
    this.candleManager.processTrades
  );

  this.candleManager.on(
    'candles',
    this.pushCandles
  );

  Readable.call(this, {objectMode: true});

  this.get();
}

var Readable = require('stream').Readable;
Market.prototype = Object.create(Readable.prototype, {
  constructor: { value: Market }
});

Market.prototype._read = _.noop;

Market.prototype.pushCandles = function(candles) {
  _.each(candles, this.push);
}

Market.prototype.get = function() {
  this.fetcher.fetch();
}

Market.prototype.processTrades = function(trades) {
  this.tradeBatcher.write(trades);

  if(this.done) {
    log.info('Done importing!');
    this.emit('end');
    return;
  }

  if(_.size(trades) && gekkoEnv === 'child-process') {
    let lastAtTS = _.last(trades).date;
    let lastAt = moment.unix(lastAtTS).utc().format();
    process.send({event: 'marketUpdate', payload: lastAt});
  }

  setTimeout(this.get, 1000);
}

module.exports = Market;


================================================
FILE: core/markets/leech.js
================================================
// a leech market is "semi-realtime" and pulls out candles of a
// database (which is expected to be updated regularly, like with a
// realtime market running in parallel).

const _ = require('lodash');
const moment = require('moment');

const util = require('../util');
const dirs = util.dirs();
const config = util.getConfig();

const exchangeChecker = require(dirs.gekko + 'exchange/exchangeChecker');

const adapter = config[config.adapter];
const Reader = require(dirs.gekko + adapter.path + '/reader');

const TICKINTERVAL = 20 * 1000; // 20 seconds

const slug = config.watch.exchange.toLowerCase();
const exchange = exchangeChecker.getExchangeCapabilities(slug);

if(!exchange)
  util.die(`Unsupported exchange: ${slug}`)

const error = exchangeChecker.cantMonitor(config.watch);
if(error)
  util.die(error, true);

if(config.market.from)
  var fromTs = moment.utc(config.market.from).unix();
else
  var fromTs = moment().startOf('minute').unix();


var Market = function() {

  _.bindAll(this);

  Readable.call(this, {objectMode: true});

  this.reader = new Reader();
  this.latestTs = fromTs;

  setInterval(
    this.get,
    TICKINTERVAL
  );
}

var Readable = require('stream').Readable;
Market.prototype = Object.create(Readable.prototype, {
  constructor: { value: Market }
});

Market.prototype._read = _.once(function() {
  this.get();
});

Market.prototype.get = function() {
  var future = moment().add(1, 'minute').unix();

  this.reader.get(
    this.latestTs,
    future,
    'full',
    this.processCandles
  )
}

Market.prototype.processCandles = function(err, candles) {
  var amount = _.size(candles);
  if(amount === 0) {
    // no new candles!
    return;
  }

  // TODO:
  // verify that the correct amount of candles was passed:
  //
  // if `this.latestTs` was at 10:00 and we receive 3 candles with the latest at 11:00
  // we know we are missing 57 candles...

  _.each(candles, function(c, i) {
    c.start = moment.unix(c.start).utc();
    this.push(c);
  }, this);

  this.latestTs = _.last(candles).start.unix() + 1;
}

module.exports = Market;


================================================
FILE: core/markets/realtime.js
================================================
const _ = require('lodash');

const util = require('../util');
const dirs = util.dirs();

const exchangeChecker = require(dirs.gekko + 'exchange/exchangeChecker');
const config = util.getConfig();

const slug = config.watch.exchange.toLowerCase();
const exchange = exchangeChecker.getExchangeCapabilities(slug);

if(!exchange)
  util.die(`Unsupported exchange: ${slug}`)

const error = exchangeChecker.cantMonitor(config.watch);
if(error)
  util.die(error, true);

module.exports = require(dirs.budfox + 'budfox');

================================================
FILE: core/pipeline.js
================================================
/*

  A pipeline implements a full Gekko Flow based on a config and 
  a mode. The mode is an abstraction that tells Gekko what market
  to load (realtime, backtesting or importing) while making sure
  all enabled plugins are actually supported by that market.

  Read more here:
  https://gekko.wizb.it/docs/internals/architecture.html

*/


var util = require('./util');
var dirs = util.dirs();

var _ = require('lodash');
var async = require('async');

var log = require(dirs.core + 'log');

var pipeline = (settings) => {

  var mode = settings.mode;
  var config = settings.config;

  // prepare a GekkoStream
  var GekkoStream = require(dirs.core + 'gekkoStream');

  // all plugins
  var plugins = [];
  // all emitting plugins
  var emitters = {};
  // all plugins interested in candles
  var candleConsumers = [];

  // utility to check and load plugins.
  var pluginHelper = require(dirs.core + 'pluginUtil');

  // meta information about every plugin that tells Gekko
  // something about every available plugin
  var pluginParameters = require(dirs.gekko + 'plugins');
  // meta information about the events plugins can broadcast
  // and how they should hooked up to consumers.
  var subscriptions = require(dirs.gekko + 'subscriptions');

  var market;

  // Instantiate each enabled plugin
  var loadPlugins = function(next) {
    // load all plugins
    async.mapSeries(
      pluginParameters,
      pluginHelper.load,
      function(error, _plugins) {
        if(error)
          return util.die(error, true);

        plugins = _.compact(_plugins);
        next();
      }
    );
  };

  // Some plugins emit their own events, store
  // a reference to those plugins.
  var referenceEmitters = function(next) {

    _.each(plugins, function(plugin) {
      if(plugin.meta.emits)
        emitters[plugin.meta.slug] = plugin;
    });

    next();
  }

  // Subscribe all plugins to other emitting plugins
  var subscribePlugins = function(next) {
    // events broadcasted by plugins
    var pluginSubscriptions = _.filter(
      subscriptions,
      sub => sub.emitter !== 'market'
    );

    // some events can be broadcasted by different
    // plugins, however the pipeline only allows a single
    // emitting plugin for each event to be enabled.
    _.each(
      pluginSubscriptions.filter(s => _.isArray(s.emitter)),
      subscription => {
        // cache full list
        subscription.emitters = subscription.emitter;
        var singleEventEmitters = subscription.emitter
          .filter(
            s => _.size(plugins.filter(p => p.meta.slug === s))
          );

        if(_.size(singleEventEmitters) > 1) {
          var error = `Multiple plugins are broadcasting`;
          error += ` the event "${subscription.event}" (${singleEventEmitters.join(',')}).`;
          error += 'This is unsupported.'
          util.die(error);
        } else {
          subscription.emitter = _.first(singleEventEmitters);
        }
      }
    );

    // subscribe interested plugins to
    // emitting plugins
    _.each(plugins, function(plugin) {
      _.each(pluginSubscriptions, function(sub) {

        if(plugin[sub.handler]) {
          // if a plugin wants to listen
          // to something disabled
          if(!emitters[sub.emitter]) {
            if(!plugin.meta.greedy) {

              let emitterMessage;
              if(sub.emitters) {
                emitterMessage = 'all of the emitting plugins [ ';
                emitterMessage += sub.emitters.join(', ');
                emitterMessage += ' ] are disabled.';
              } else {
                emitterMessage += 'the emitting plugin (' + sub.emitter;
                emitterMessage += ')is disabled.'
              }

              log.error([
                plugin.meta.name,
                'wanted to listen to event',
                sub.event + ',',
                'however',
                emitterMessage,
                plugin.meta.name + ' might malfunction because of it.'
              ].join(' '));
            }
            return;
          }

          // attach handler
          emitters[sub.emitter]
            .on(sub.event,
              plugin[
                sub.handler
              ])
        }

      });
    });

    // events broadcasted by the market
    var marketSubscriptions = _.filter(
      subscriptions,
      {emitter: 'market'}
    );

    // subscribe plugins to the market
    _.each(plugins, function(plugin) {
      _.each(marketSubscriptions, function(sub) {

        if(plugin[sub.handler]) {
          if(sub.event === 'candle')
            candleConsumers.push(plugin);
        }

      });
    });

    next();
  }

  var prepareMarket = function(next) {
    if(mode === 'backtest' && config.backtest.daterange === 'scan')
      require(dirs.core + 'prepareDateRange')(next);
    else
      next();
  }

  var setupMarket = function(next) {
    // load a market based on the config (or fallback to mode)
    let marketType;
    if(config.market)
      marketType = config.market.type;
    else
      marketType = mode;

    var Market = require(dirs.markets + marketType);

    market = new Market(config);

    next();
  }

  var subscribePluginsToMarket = function(next) {

    // events broadcasted by the market
    var marketSubscriptions = _.filter(
      subscriptions,
      {emitter: 'market'}
    );

    _.each(plugins, function(plugin) {
      _.each(marketSubscriptions, function(sub) {

        if(sub.event === 'candle')
          // these are handled via the market stream
          return;

        if(plugin[sub.handler]) {
          market.on(sub.event, plugin[sub.handler]);
        }

      });
    });

    next();

  }

  log.info('Setting up Gekko in', mode, 'mode');
  log.info('');

  async.series(
    [
      loadPlugins,
      referenceEmitters,
      subscribePlugins,
      prepareMarket,
      setupMarket,
      subscribePluginsToMarket
    ],
    function() {

      var gekkoStream = new GekkoStream(plugins);

      market
        .pipe(gekkoStream)

        // convert JS objects to JSON string
        // .pipe(new require('stringify-stream')())
        // output to standard out
        // .pipe(process.stdout);

      market.on('end', gekkoStream.finalize);
    }
  );

}

module.exports = pipeline;

================================================
FILE: core/pluginUtil.js
================================================
var _ = require('lodash');
var async = require('async');
var Emitter = require('./emitter');

var util = require(__dirname + '/util');

var log = require(util.dirs().core + 'log');

var config = util.getConfig();
var pluginDir = util.dirs().plugins;
var gekkoMode = util.gekkoMode();
var inherits = require('util').inherits;

var pluginHelper = {
  // Checks whether we can load a module

  // @param Object plugin
  //    plugin config object
  // @return String
  //    error message if we can't
  //    use the module.
  cannotLoad: function(plugin) {

    // verify plugin dependencies are installed
    if(_.has(plugin, 'dependencies'))
      var error = false;

      _.each(plugin.dependencies, function(dep) {
        try {
          var a = require(dep.module);
        }
        catch(e) {
          log.error('ERROR LOADING DEPENDENCY', dep.module);

          if(!e.message) {
            log.error(e);
            util.die();
          }

          if(!e.message.startsWith('Cannot find module'))
            return util.die(e);

          error = [
            'The plugin',
            plugin.slug,
            'expects the module',
            dep.module,
            'to be installed.',
            'However it is not, install',
            'it by running: \n\n',
            '\tnpm install',
            dep.module + '@' + dep.version
          ].join(' ');
        }
      });

    return error;
  },
  // loads a plugin
  // 
  // @param Object plugin
  //    plugin config object
  // @param Function next
  //    callback
  load: function(plugin, next) {

    plugin.config = config[plugin.slug];

    if(!plugin.config || !plugin.config.enabled)
      return next();

    if(!_.contains(plugin.modes, gekkoMode)) {
      log.warn(
        'The plugin',
        plugin.name,
        'does not support the mode',
        gekkoMode + '.',
        'It has been disabled.'
      )
      return next();
    }

    log.info('Setting up:');
    log.info('\t', plugin.name);
    log.info('\t', plugin.description);

    var cannotLoad = pluginHelper.cannotLoad(plugin);
    if(cannotLoad)
      return next(cannotLoad);

    if(plugin.path)
      var Constructor = require(pluginDir + plugin.path(config));
    else
      var Constructor = require(pluginDir + plugin.slug);

    if(plugin.async) {
      inherits(Constructor, Emitter);
      var instance = new Constructor(util.defer(function(err) {
        next(err, instance);
      }), plugin);
      Emitter.call(instance);

      instance.meta = plugin;
    } else {
      inherits(Constructor, Emitter);
      var instance = new Constructor(plugin);
      Emitter.call(instance);

      instance.meta = plugin;
      _.defer(function() {
        next(null, instance); 
      });
    }

    if(!plugin.silent)
      log.info('\n');
  }
}

module.exports = pluginHelper;

================================================
FILE: core/prepareDateRange.js
================================================
var _ = require('lodash');
var prompt = require('prompt-lite');
var moment = require('moment');

var util = require('./util');
var config = util.getConfig();
var dirs = util.dirs();
var log = require(dirs.core + 'log');

var scan = require(dirs.tools + 'dateRangeScanner');

// helper to store the evenutally detected
// daterange.
var setDateRange = function(from, to) {
  config.backtest.daterange = {
    from: moment.unix(from).utc().format(),
    to: moment.unix(to).utc().format(),
  };
  util.setConfig(config);
}


module.exports = function(done) {
  scan((err, ranges) => {

    if(_.size(ranges) === 0)
      util.die('No history found for this market', true);

    if(_.size(ranges) === 1) {
      var r = _.first(ranges);
      log.info('Gekko was able to find a single daterange in the locally stored history:');
      log.info('\t', 'from:', moment.unix(r.from).utc().format('YYYY-MM-DD HH:mm:ss'));
      log.info('\t', 'to:', moment.unix(r.to).utc().format('YYYY-MM-DD HH:mm:ss'));

      
      setDateRange(r.from, r.to);
      return done();
    }

    log.info(
      'Gekko detected multiple dateranges in the locally stored history.',
      'Please pick the daterange you are interested in testing:'
    );

    _.each(ranges, (range, i) => {
      log.info('\t\t', `OPTION ${i + 1}:`);
      log.info('\t', 'from:', moment.unix(range.from).utc().format('YYYY-MM-DD HH:mm:ss'));
      log.info('\t', 'to:', moment.unix(range.to).utc().format('YYYY-MM-DD HH:mm:ss'));
    });

    prompt.get({name: 'option'}, (err, result) => {

      var option = parseInt(result.option);
      if(option === NaN)
        util.die('Not an option..', true);

      var range = ranges[option - 1];

      if(!range)
        util.die('Not an option..', true);

      setDateRange(range.from, range.to);
      return done();
    });

  });
}

================================================
FILE: core/stats.js
================================================
const stats = require('stats-lite');
const lodash = require('lodash');


// simply monkey patch the stats with other stuff we
// need and pass on.

// sharpe ratio
//
// @param returns (array - list of returns)
// @param rfreturn (number - risk free return)
// 
stats.sharpe = (returns, rfreturn) => {
  return (stats.mean(returns) - rfreturn) / stats.stdev(returns);
}

module.exports = stats;


================================================
FILE: core/talib.js
================================================
var semver = require("semver");
var _ = require('lodash');

// validate that talib is installed, if not we'll throw an exception which will
// prevent further loading or out outside this module
try {
    var talib = require("talib");
} catch (e) {
    module.exports = null;
    return;
}

var talibError = 'Gekko was unable to configure talib indicator:\n\t';
var talibGTEv103 = semver.gte(talib.version, '1.0.3');

// Wrapper that executes a talib indicator
var execute = function(callback, params) {
    // talib callback style since talib-v1.0.3
    var talibCallback = function(err, result) {
        if(err) return callback(err);
        callback(null, result.result);
    };

    // talib legacy callback style before talib-v1.0.3
    var talibLegacyCallback = function(result) {
        var error = result.error;
        talibCallback.apply(this, [error, result]);
    };

    return talib.execute(params, talibGTEv103 ? talibCallback : talibLegacyCallback);
}

// Helper that makes sure all required parameters
// for a specific talib indicator are present.
var verifyParams = (methodName, params) => {
    var requiredParams = methods[methodName].requires;

    _.each(requiredParams, paramName => {
        if(!_.has(params, paramName)) {
            throw new Error(talibError + methodName + ' requires ' + paramName + '.');
        }

        var val = params[paramName];

        if(!_.isNumber(val)) {
            throw new Error(talibError + paramName + ' needs to be a number');
        }
    });
}

var methods = {};


//////////////////////////////Pattern Recognition//////////////////////////////
methods.cdl2crows = {
    requires: [],
    create: (params) => {
        verifyParams('cdl2crows', params);
        return (data, callback) => execute(callback, {
            name: "CDL2CROWS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdl3blackcrows = {
    requires: [],
    create: (params) => {
        verifyParams('cdl3blackcrows', params);
        return (data, callback) => execute(callback, {
            name: "CDL3BLACKCROWS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdl3inside = {
    requires: [],
    create: (params) => {
        verifyParams('cdl3inside', params);
        return (data, callback) => execute(callback, {
            name: "CDL3INSIDE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdl3linestrike = {
    requires: [],
    create: (params) => {
        verifyParams('cdl3linestrike', params);
        return (data, callback) => execute(callback, {
            name: "CDL3LINESTRIKE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdl3outside = {
    requires: [],
    create: (params) => {
        verifyParams('cdl3outside', params);
        return (data, callback) => execute(callback, {
            name: "CDL3OUTSIDE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdl3starsinsouth = {
    requires: [],
    create: (params) => {
        verifyParams('cdl3starsinsouth', params);
        return (data, callback) => execute(callback, {
            name: "CDL3STARSINSOUTH",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdl3whitesoldiers = {
    requires: [],
    create: (params) => {
        verifyParams('cdl3whitesoldiers', params);
        return (data, callback) => execute(callback, {
            name: "CDL3WHITESOLDIERS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlabandonedbaby = {
    requires: ['optInPenetration'],
    create: (params) => {
        verifyParams('cdlabandonedbaby', params);
        return (data, callback) => execute(callback, {
            name: "CDLABANDONEDBABY",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            optInPenetration: params.optInPenetration
        });
    }
}
methods.cdladvanceblock = {
    requires: [],
    create: (params) => {
        verifyParams('cdladvanceblock', params);
        return (data, callback) => execute(callback, {
            name: "CDLADVANCEBLOCK",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlbelthold = {
    requires: [],
    create: (params) => {
        verifyParams('cdlbelthold', params);
        return (data, callback) => execute(callback, {
            name: "CDLBELTHOLD",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlbreakaway = {
    requires: [],
    create: (params) => {
        verifyParams('cdlbreakaway', params);
        return (data, callback) => execute(callback, {
            name: "CDLBREAKAWAY",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlclosingmarubozu = {
    requires: [],
    create: (params) => {
        verifyParams('cdlclosingmarubozu', params);
        return (data, callback) => execute(callback, {
            name: "CDLCLOSINGMARUBOZU",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlconcealbabyswall = {
    requires: [],
    create: (params) => {
        verifyParams('cdlconcealbabyswall', params);
        return (data, callback) => execute(callback, {
            name: "CDLCONCEALBABYSWALL",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlcounterattack = {
    requires: [],
    create: (params) => {
        verifyParams('cdlcounterattack', params);
        return (data, callback) => execute(callback, {
            name: "CDLCOUNTERATTACK",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdldarkcloudcover = {
    requires: ['optInPenetration'],
    create: (params) => {
        verifyParams('cdldarkcloudcover', params);
        return (data, callback) => execute(callback, {
            name: "CDLDARKCLOUDCOVER",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            optInPenetration: params.optInPenetration
        });
    }
}
methods.cdldoji = {
    requires: [],
    create: (params) => {
        verifyParams('cdldoji', params);
        return (data, callback) => execute(callback, {
            name: "CDLDOJI",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdldojistar = {
    requires: [],
    create: (params) => {
        verifyParams('cdldojistar', params);
        return (data, callback) => execute(callback, {
            name: "CDLDOJISTAR",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdldragonflydoji = {
    requires: [],
    create: (params) => {
        verifyParams('cdldragonflydoji', params);
        return (data, callback) => execute(callback, {
            name: "CDLDRAGONFLYDOJI",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlengulfing = {
    requires: [],
    create: (params) => {
        verifyParams('cdlengulfing', params);
        return (data, callback) => execute(callback, {
            name: "CDLENGULFING",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdleveningdojistar = {
    requires: ['optInPenetration'],
    create: (params) => {
        verifyParams('cdleveningdojistar', params);
        return (data, callback) => execute(callback, {
            name: "CDLEVENINGDOJISTAR",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            optInPenetration: params.optInPenetration
        });
    }
}
methods.cdleveningstar = {
    requires: ['optInPenetration'],
    create: (params) => {
        verifyParams('cdleveningstar', params);
        return (data, callback) => execute(callback, {
            name: "CDLEVENINGSTAR",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            optInPenetration: params.optInPenetration
        });
    }
}
methods.cdlgapsidesidewhite = {
    requires: [],
    create: (params) => {
        verifyParams('cdlgapsidesidewhite', params);
        return (data, callback) => execute(callback, {
            name: "CDLGAPSIDESIDEWHITE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlgravestonedoji = {
    requires: [],
    create: (params) => {
        verifyParams('cdlgravestonedoji', params);
        return (data, callback) => execute(callback, {
            name: "CDLGRAVESTONEDOJI",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlhammer = {
    requires: [],
    create: (params) => {
        verifyParams('cdlhammer', params);
        return (data, callback) => execute(callback, {
            name: "CDLHAMMER",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlhangingman = {
    requires: [],
    create: (params) => {
        verifyParams('cdlhangingman', params);
        return (data, callback) => execute(callback, {
            name: "CDLHANGINGMAN",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlharami = {
    requires: [],
    create: (params) => {
        verifyParams('cdlharami', params);
        return (data, callback) => execute(callback, {
            name: "CDLHARAMI",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlharamicross = {
    requires: [],
    create: (params) => {
        verifyParams('cdlharamicross', params);
        return (data, callback) => execute(callback, {
            name: "CDLHARAMICROSS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlhighwave = {
    requires: [],
    create: (params) => {
        verifyParams('cdlhighwave', params);
        return (data, callback) => execute(callback, {
            name: "CDLHIGHWAVE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlhikkake = {
    requires: [],
    create: (params) => {
        verifyParams('cdlhikkake', params);
        return (data, callback) => execute(callback, {
            name: "CDLHIKKAKE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlhikkakemod = {
    requires: [],
    create: (params) => {
        verifyParams('cdlhikkakemod', params);
        return (data, callback) => execute(callback, {
            name: "CDLHIKKAKEMOD",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlhomingpigeon = {
    requires: [],
    create: (params) => {
        verifyParams('cdlhomingpigeon', params);
        return (data, callback) => execute(callback, {
            name: "CDLHOMINGPIGEON",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlidentical3crows = {
    requires: [],
    create: (params) => {
        verifyParams('cdlidentical3crows', params);
        return (data, callback) => execute(callback, {
            name: "CDLIDENTICAL3CROWS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlinneck = {
    requires: [],
    create: (params) => {
        verifyParams('cdlinneck', params);
        return (data, callback) => execute(callback, {
            name: "CDLINNECK",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlinvertedhammer = {
    requires: [],
    create: (params) => {
        verifyParams('cdlinvertedhammer', params);
        return (data, callback) => execute(callback, {
            name: "CDLINVERTEDHAMMER",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlkicking = {
    requires: [],
    create: (params) => {
        verifyParams('cdlkicking', params);
        return (data, callback) => execute(callback, {
            name: "CDLKICKING",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlkickingbylength = {
    requires: [],
    create: (params) => {
        verifyParams('cdlkickingbylength', params);
        return (data, callback) => execute(callback, {
            name: "CDLKICKINGBYLENGTH",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlladderbottom = {
    requires: [],
    create: (params) => {
        verifyParams('cdlladderbottom', params);
        return (data, callback) => execute(callback, {
            name: "CDLLADDERBOTTOM",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdllongleggeddoji = {
    requires: [],
    create: (params) => {
        verifyParams('cdllongleggeddoji', params);
        return (data, callback) => execute(callback, {
            name: "CDLLONGLEGGEDDOJI",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdllongline = {
    requires: [],
    create: (params) => {
        verifyParams('cdllongline', params);
        return (data, callback) => execute(callback, {
            name: "CDLLONGLINE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlmarubozu = {
    requires: [],
    create: (params) => {
        verifyParams('cdlmarubozu', params);
        return (data, callback) => execute(callback, {
            name: "CDLMARUBOZU",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlmatchinglow = {
    requires: [],
    create: (params) => {
        verifyParams('cdlmatchinglow', params);
        return (data, callback) => execute(callback, {
            name: "CDLMATCHINGLOW",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlmathold = {
    requires: ['optInPenetration'],
    create: (params) => {
        verifyParams('cdlmathold', params);
        return (data, callback) => execute(callback, {
            name: "CDLMATHOLD",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            optInPenetration: params.optInPenetration
        });
    }
}
methods.cdlmorningdojistar = {
    requires: ['optInPenetration'],
    create: (params) => {
        verifyParams('cdlmorningdojistar', params);
        return (data, callback) => execute(callback, {
            name: "CDLMORNINGDOJISTAR",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            optInPenetration: params.optInPenetration
        });
    }
}
methods.cdlmorningstar = {
    requires: ['optInPenetration'],
    create: (params) => {
        verifyParams('cdlmorningstar', params);
        return (data, callback) => execute(callback, {
            name: "CDLMORNINGSTAR",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            optInPenetration: params.optInPenetration
        });
    }
}
methods.cdlonneck = {
    requires: [],
    create: (params) => {
        verifyParams('cdlonneck', params);
        return (data, callback) => execute(callback, {
            name: "CDLONNECK",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlpiercing = {
    requires: [],
    create: (params) => {
        verifyParams('cdlpiercing', params);
        return (data, callback) => execute(callback, {
            name: "CDLPIERCING",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlrickshawman = {
    requires: [],
    create: (params) => {
        verifyParams('cdlrickshawman', params);
        return (data, callback) => execute(callback, {
            name: "CDLRICKSHAWMAN",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlrisefall3methods = {
    requires: [],
    create: (params) => {
        verifyParams('cdlrisefall3methods', params);
        return (data, callback) => execute(callback, {
            name: "CDLRISEFALL3METHODS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlseparatinglines = {
    requires: [],
    create: (params) => {
        verifyParams('cdlseparatinglines', params);
        return (data, callback) => execute(callback, {
            name: "CDLSEPARATINGLINES",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlshootingstar = {
    requires: [],
    create: (params) => {
        verifyParams('cdlshootingstar', params);
        return (data, callback) => execute(callback, {
            name: "CDLSHOOTINGSTAR",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlshortline = {
    requires: [],
    create: (params) => {
        verifyParams('cdlshortline', params);
        return (data, callback) => execute(callback, {
            name: "CDLSHORTLINE",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlspinningtop = {
    requires: [],
    create: (params) => {
        verifyParams('cdlspinningtop', params);
        return (data, callback) => execute(callback, {
            name: "CDLSPINNINGTOP",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlstalledpattern = {
    requires: [],
    create: (params) => {
        verifyParams('cdlstalledpattern', params);
        return (data, callback) => execute(callback, {
            name: "CDLSTALLEDPATTERN",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlsticksandwich = {
    requires: [],
    create: (params) => {
        verifyParams('cdlsticksandwich', params);
        return (data, callback) => execute(callback, {
            name: "CDLSTICKSANDWICH",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdltakuri = {
    requires: [],
    create: (params) => {
        verifyParams('cdltakuri', params);
        return (data, callback) => execute(callback, {
            name: "CDLTAKURI",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdltasukigap = {
    requires: [],
    create: (params) => {
        verifyParams('cdltasukigap', params);
        return (data, callback) => execute(callback, {
            name: "CDLTASUKIGAP",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlthrusting = {
    requires: [],
    create: (params) => {
        verifyParams('cdlthrusting', params);
        return (data, callback) => execute(callback, {
            name: "CDLTHRUSTING",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdltristar = {
    requires: [],
    create: (params) => {
        verifyParams('cdltristar', params);
        return (data, callback) => execute(callback, {
            name: "CDLTRISTAR",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlunique3river = {
    requires: [],
    create: (params) => {
        verifyParams('cdlunique3river', params);
        return (data, callback) => execute(callback, {
            name: "CDLUNIQUE3RIVER",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlupsidegap2crows = {
    requires: [],
    create: (params) => {
        verifyParams('cdlupsidegap2crows', params);
        return (data, callback) => execute(callback, {
            name: "CDLUPSIDEGAP2CROWS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}
methods.cdlxsidegap3methods = {
    requires: [],
    create: (params) => {
        verifyParams('cdlxsidegap3methods', params);
        return (data, callback) => execute(callback, {
            name: "CDLXSIDEGAP3METHODS",
            startIdx: 0,
            endIdx: data.close.length - 1,
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close
        });
    }
}

//////////////////////////////Pattern Recognition//////////////////////////////

methods.accbands = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('accbands', params);

        return (data, callback) => execute(callback, {
            name: "ACCBANDS",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.ad = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('accbands', params);

        return (data, callback) => execute(callback, {
            name: "AD",
            high: data.high,
            low: data.low,
            close: data.close,
            volume: data.volume,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.adosc = {
    requires: ['optInFastPeriod', 'optInSlowPeriod'],
    create: (params) => {
        verifyParams('adosc', params);

        return (data, callback) => execute(callback, {
            name: "ADOSC",
            high: data.high,
            low: data.low,
            close: data.close,
            volume: data.volume,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInFastPeriod: params.optInFastPeriod,
            optInSlowPeriod: params.optInSlowPeriod
        });
    }
}

methods.adx = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('adx', params);

        return (data, callback) => execute(callback, {
            name: "ADX",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.adxr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('adxr', params);

        return (data, callback) => execute(callback, {
            name: "ADXR",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.apo = {
    requires: ['optInFastPeriod', 'optInSlowPeriod', 'optInMAType'],
    create: (params) => {
        verifyParams('apo', params);

        return (data, callback) => execute(callback, {
            name: "APO",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.length - 1,
            optInFastPeriod: params.optInFastPeriod,
            optInSlowPeriod: params.optInSlowPeriod,
            optInMAType: params.optInMAType
        });
    }
}

methods.aroon = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('aroon', params);

        return (data, callback) => execute(callback, {
            name: "AROON",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.aroonosc = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('aroonosc', params);

        return (data, callback) => execute(callback, {
            name: "AROONOSC",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.atr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('atr', params);

        return (data, callback) => execute(callback, {
            name: "ATR",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.avgprice = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('avgprice', params);

        return (data, callback) => execute(callback, {
            name: "AVGPRICE",
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.open.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.bbands = {
    requires: ['optInTimePeriod', 'optInNbDevUp', 'optInNbDevDn', 'optInMAType'],
    create: (params) => {
        verifyParams('bbands', params);

        return (data, callback) => execute(callback, {
            name: "BBANDS",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod,
            optInNbDevUp: params.optInNbDevUp,
            optInNbDevDn: params.optInNbDevDn,
            optInMAType: params.optInMAType
        });
    }
}

///////////////////////////////////////////////////////////////


// this.beta = function(data_0, data_1, period) {
//     return talibWrapper({
//         name: "BETA",
//         inReal0: data_0,
//         inReal1: data_1,
//         startIdx: 0,
//         endIdx: data_0.length - 1,
//         optInTimePeriod: period
//     });
// };

methods.bop = {
    requires: [],
    create: (params) => {
        verifyParams('bop', params);

        return (data, callback) => execute(callback, {
            name: "BOP",
            open: data.open,
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1
        });
    }
}

methods.cci = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('cci', params);

        return (data, callback) => execute(callback, {
            name: "CCI",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.cmo = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('cmo', params);

        return (data, callback) => execute(callback, {
            name: "CMO",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

// this.correl = function(data_0, data_1, period) {
//     return talibWrapper({
//         name: "CORREL",
//         inReal0: data_0,
//         inReal1: data_1,
//         startIdx: 0,
//         endIdx: data_0.length - 1,
//         optInTimePeriod: period
//     });
// };

methods.dema = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('dema', params);

        return (data, callback) => execute(callback, {
            name: "DEMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.dx = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('dx', params);

        return (data, callback) => execute(callback, {
            name: "DX",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.ema = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('ema', params);

        return (data, callback) => execute(callback, {
            name: "EMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.ht_dcperiod = {
    requires: [],
    create: (params) => {
        verifyParams('ht_dcperiod', params);

        return (data, callback) => execute(callback, {
            name: "HT_DCPERIOD",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1
        });
    }
}

methods.ht_dcphase = {
    requires: [],
    create: (params) => {
        verifyParams('ht_dcphase', params);

        return (data, callback) => execute(callback, {
            name: "HT_DCPHASE",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1
        });
    }
}

methods.ht_phasor = {
    requires: [],
    create: (params) => {
        verifyParams('ht_phasor', params);

        return (data, callback) => execute(callback, {
            name: "HT_PHASOR",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1
        });
    }
}

methods.ht_sine = {
    requires: [],
    create: (params) => {
        verifyParams('ht_sine', params);

        return (data, callback) => execute(callback, {
            name: "HT_SINE",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1
        });
    }
}


methods.ht_trendline = {
    requires: [],
    create: (params) => {
        verifyParams('ht_trendline', params);

        return (data, callback) => execute(callback, {
            name: "HT_TRENDLINE",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1
        });
    }
}

methods.ht_trendmode = {
    requires: [],
    create: (params) => {
        verifyParams('ht_trendmode', params);

        return (data, callback) => execute(callback, {
            name: "HT_TRENDMODE",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1
        });
    }
}

methods.imi = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('imi', params);

        return (data, callback) => execute(callback, {
            name: "IMI",
            open: data.open,
            close: data.close,
            startIdx: 0,
            endIdx: data.open.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.kama = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('kama', params);

        return (data, callback) => execute(callback, {
            name: "KAMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.linearreg = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('linearreg', params);

        return (data, callback) => execute(callback, {
            name: "LINEARREG",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.linearreg_angle = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('linearreg_angle', params);

        return (data, callback) => execute(callback, {
            name: "LINEARREG_ANGLE",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.linearreg_intercept = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('linearreg_intercept', params);

        return (data, callback) => execute(callback, {
            name: "LINEARREG_INTERCEPT",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.linearreg_slope = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('linearreg_slope', params);

        return (data, callback) => execute(callback, {
            name: "LINEARREG_SLOPE",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.ma = {
    requires: ['optInTimePeriod', 'optInMAType'],
    create: (params) => {
        verifyParams('ma', params);

        return (data, callback) => execute(callback, {
            name: "MA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod,
            optInMAType: params.optInMAType
        });
    }
}

methods.macd = {
    requires: ['optInFastPeriod', 'optInSlowPeriod', 'optInSignalPeriod'],
    create: (params) => {
        verifyParams('macd', params);

        return (data, callback) => execute(callback, {
            name: "MACD",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInFastPeriod: params.optInFastPeriod,
            optInSlowPeriod: params.optInSlowPeriod,
            optInSignalPeriod: params.optInSignalPeriod
        });
    }
}

methods.macdext = {
    requires: [
        'optInFastPeriod',
        'optInFastMAType',
        'optInSlowPeriod',
        'optInSlowMAType',
        'optInSignalPeriod',
        'optInSignalMAType'
    ],
    create: (params) => {
        verifyParams('macdext', params);

        return (data, callback) => execute(callback, {
            name: "MACDEXT",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInFastPeriod: params.optInFastPeriod,
            optInFastMAType: params.optInFastMAType,
            optInSlowPeriod: params.optInSlowPeriod,
            optInSlowMAType: params.optInSlowMAType,
            optInSignalPeriod: params.optInSignalPeriod,
            optInSignalMAType: params.optInSignalMAType
        });
    }
}

methods.macdfix = {
    requires: ['optInSignalPeriod'],
    create: (params) => {
        verifyParams('macdfix', params);

        return (data, callback) => execute(callback, {
            name: "MACDFIX",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInSignalPeriod: params.optInSignalPeriod
        });
    }
}

methods.mama = {
    requires: ['optInFastLimit', 'optInSlowLimit'],
    create: (params) => {
        verifyParams('mama', params);

        return (data, callback) => execute(callback, {
            name: "MAMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInFastLimit: params.optInFastLimit,
            optInSlowLimit: params.optInSlowLimit
        });
    }
}

methods.mavp = {
    requires: ['inPeriods', 'optInMinPeriod', 'optInMaxPeriod', 'optInMAType'],
    create: (params) => {
        verifyParams('mavp', params);

        return (data, callback) => execute(callback, {
            name: "MAVP",
            inReal: data.close,
            inPeriods: params.inPeriods,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInMinPeriod: params.optInMinPeriod,
            optInMaxPeriod: params.optInMaxPeriod,
            optInMAType: params.optInMAType
        });
    }
}


methods.max = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('max', params);

        return (data, callback) => execute(callback, {
            name: "MAX",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}


methods.maxindex = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('maxindex', params);

        return (data, callback) => execute(callback, {
            name: "MAXINDEX",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.medprice = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('medprice', params);

        return (data, callback) => execute(callback, {
            name: "MEDPRICE",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.mfi = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('mfi', params);

        return (data, callback) => execute(callback, {
            name: "MFI",
            high: data.high,
            low: data.low,
            close: data.close,
            volume: data.volume,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.midpoint = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('midpoint', params);

        return (data, callback) => execute(callback, {
            name: "MIDPOINT",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.midprice = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('midprice', params);

        return (data, callback) => execute(callback, {
            name: "MIDPRICE",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.min = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('min', params);

        return (data, callback) => execute(callback, {
            name: "MIN",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.minindex = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('minindex', params);

        return (data, callback) => execute(callback, {
            name: "MININDEX",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.minmax = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('minmax', params);

        return (data, callback) => execute(callback, {
            name: "MINMAX",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.minmaxindex = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('minmaxindex', params);

        return (data, callback) => execute(callback, {
            name: "MINMAXINDEX",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.minus_di = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('minus_di', params);

        return (data, callback) => execute(callback, {
            name: "MINUS_DI",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.minus_dm = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('minus_dm', params);

        return (data, callback) => execute(callback, {
            name: "MINUS_DM",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.mom = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('mom', params);

        return (data, callback) => execute(callback, {
            name: "MOM",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.natr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('natr', params);

        return (data, callback) => execute(callback, {
            name: "NATR",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.obv = {
    requires: [],
    create: (params) => {
        verifyParams('obv', params);

        return (data, callback) => execute(callback, {
            name: "OBV",
            inReal: data.close,
            volume: data.volume,
            startIdx: 0,
            endIdx: data.close.length - 1
        });
    }
}

methods.plus_di = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('plus_di', params);

        return (data, callback) => execute(callback, {
            name: "PLUS_DI",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.plus_dm = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('plus_dm', params);

        return (data, callback) => execute(callback, {
            name: "PLUS_DM",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.ppo = {
    requires: ['optInFastPeriod', 'optInSlowPeriod', 'optInMAType'],
    create: (params) => {
        verifyParams('ppo', params);

        return (data, callback) => execute(callback, {
            name: "PPO",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInFastPeriod: params.optInFastPeriod,
            optInSlowPeriod: params.optInSlowPeriod,
            optInMAType: params.optInMAType
        });
    }
}

methods.roc = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('roc', params);

        return (data, callback) => execute(callback, {
            name: "ROC",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.rocp = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('rocp', params);

        return (data, callback) => execute(callback, {
            name: "ROCP",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.rocr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('rocr', params);

        return (data, callback) => execute(callback, {
            name: "ROCR",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.rocr100 = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('rocr100', params);

        return (data, callback) => execute(callback, {
            name: "ROCR100",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.rsi = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('rsi', params);

        return (data, callback) => execute(callback, {
            name: "RSI",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.sar = {
    requires: ['optInAcceleration', 'optInMaximum'],
    create: (params) => {
        verifyParams('sar', params);

        return (data, callback) => execute(callback, {
            name: "SAR",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInAcceleration: params.optInAcceleration,
            optInMaximum: params.optInMaximum
        });
    }
}

methods.sarext = {
    requires: [
        'optInStartValue',
        'optInOffsetOnReverse',
        'optInAccelerationInitLong',
        'optInAccelerationLong',
        'optInAccelerationMaxLong',
        'optInAccelerationInitShort',
        'optInAccelerationShort',
        'optInAccelerationMaxShort'

    ],
    create: (params) => {
        verifyParams('sarext', params);

        return (data, callback) => execute(callback, {
            name: "SAREXT",
            high: data.high,
            low: data.low,
            startIdx: 0,
            endIdx: data.high.length - 1,

            optInStartValue: params.optInStartValue,
            optInOffsetOnReverse: params.optInOffsetOnReverse,
            optInAccelerationInitLong: params.optInAccelerationInitLong,
            optInAccelerationLong: params.optInAccelerationLong,
            optInAccelerationMaxLong: params.optInAccelerationMaxLong,
            optInAccelerationInitShort: params.optInAccelerationInitShort,
            optInAccelerationShort: params.optInAccelerationShort,
            optInAccelerationMaxShort: params.optInAccelerationMaxShort
        });
    }
}

methods.sma = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('sma', params);

        return (data, callback) => execute(callback, {
            name: "SMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.stddev = {
    requires: ['optInTimePeriod', 'optInNbDev'],
    create: (params) => {
        verifyParams('stddev', params);

        return (data, callback) => execute(callback, {
            name: "STDDEV",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod,
            optInNbDev: params.optInNbDev
        });
    }
}

methods.stoch = {
    requires: [
        'optInFastK_Period',
        'optInSlowK_Period',
        'optInSlowK_MAType',
        'optInSlowD_Period',
        'optInSlowD_MAType'
    ],
    create: (params) => {
        verifyParams('stoch', params);

        return (data, callback) => execute(callback, {
            name: "STOCH",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,

            optInFastK_Period: params.optInFastK_Period,
            optInSlowK_Period: params.optInSlowK_Period,
            optInSlowK_MAType: params.optInSlowK_MAType,
            optInSlowD_Period: params.optInSlowD_Period,
            optInSlowD_MAType: params.optInSlowD_MAType
        });
    }
}


methods.stochf = {
    requires: [
        'optInFastK_Period',
        'optInFastD_Period',
        'optInFastD_MAType'
    ],
    create: (params) => {
        verifyParams('stochf', params);

        return (data, callback) => execute(callback, {
            name: "STOCHF",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,

            optInFastK_Period: params.optInFastK_Period,
            optInFastD_Period: params.optInFastD_Period,
            optInFastD_MAType: params.optInFastD_MAType
        });
    }
}

methods.stochrsi = {
    requires: [
        'optInTimePeriod',
        'optInFastK_Period',
        'optInFastD_Period',
        'optInFastD_MAType'
    ],
    create: (params) => {
        verifyParams('stochrsi', params);

        return (data, callback) => execute(callback, {
            name: "STOCHRSI",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,

            optInTimePeriod: params.optInTimePeriod,
            optInFastK_Period: params.optInFastK_Period,
            optInFastD_Period: params.optInFastD_Period,
            optInFastD_MAType: params.optInFastD_MAType
        });
    }
}

methods.t3 = {
    requires: [
        'optInTimePeriod',
        'optInFastK_Period',
        'optInFastD_Period',
        'optInFastD_MAType'
    ],
    create: (params) => {
        verifyParams('t3', params);

        return (data, callback) => execute(callback, {
            name: "T3",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod,
            optInVFactor: params.optInVFactor
        });
    }
}

methods.tema = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('tema', params);

        return (data, callback) => execute(callback, {
            name: "TEMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.trange = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('trange', params);

        return (data, callback) => execute(callback, {
            name: "TRANGE",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.trima = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('trima', params);

        return (data, callback) => execute(callback, {
            name: "TRIMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.trix = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('trix', params);

        return (data, callback) => execute(callback, {
            name: "TRIX",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.tsf = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('tsf', params);

        return (data, callback) => execute(callback, {
            name: "TSF",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.typprice = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('typprice', params);

        return (data, callback) => execute(callback, {
            name: "TYPPRICE",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.ultosc = {
    requires: ['optInTimePeriod1', 'optInTimePeriod2', 'optInTimePeriod3'],
    create: (params) => {
        verifyParams('ultosc', params);

        return (data, callback) => execute(callback, {
            name: "ULTOSC",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod1: params.optInTimePeriod1,
            optInTimePeriod2: params.optInTimePeriod2,
            optInTimePeriod3: params.optInTimePeriod3
        });
    }
}

methods.variance = {
    requires: ['optInTimePeriod', 'optInNbDev'],
    create: (params) => {
        verifyParams('variance', params);

        return (data, callback) => execute(callback, {
            name: "VAR",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod,
            optInNbDev: params.optInTimePeriod
        });
    }
}

methods.wclprice = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('wclprice', params);

        return (data, callback) => execute(callback, {
            name: "WCLPRICE",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.willr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('willr', params);

        return (data, callback) => execute(callback, {
            name: "WILLR",
            high: data.high,
            low: data.low,
            close: data.close,
            startIdx: 0,
            endIdx: data.high.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

methods.wma = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('wma', params);

        return (data, callback) => execute(callback, {
            name: "WMA",
            inReal: data.close,
            startIdx: 0,
            endIdx: data.close.length - 1,
            optInTimePeriod: params.optInTimePeriod
        });
    }
}

module.exports = methods;



================================================
FILE: core/tools/candleLoader.js
================================================
// TODO: properly handle a daterange for which no data is available.

const batchSize = 1000;

const _ = require('lodash');
const fs = require('fs');
const moment = require('moment');

const util = require('../../core/util');
const config = util.getConfig();
const dirs = util.dirs();
const log = require(dirs.core + '/log');

const adapter = config[config.adapter];
const Reader = require(dirs.gekko + adapter.path + '/reader');
const daterange = config.daterange;

const CandleBatcher = require(dirs.core + 'candleBatcher');

const to = moment.utc(daterange.to).startOf('minute');
const from = moment.utc(daterange.from).startOf('minute');
const toUnix = to.unix();

if(to <= from)
  util.die('This daterange does not make sense.')

if(!from.isValid())
  util.die('invalid `from`');

if(!to.isValid())
  util.die('invalid `to`');

let iterator = {
  from: from.clone(),
  to: from.clone().add(batchSize, 'm').subtract(1, 's')
}

var DONE = false;

var result = [];
var reader = new Reader();
var batcher;
var next;
var doneFn = () => {
  process.nextTick(() => {
    next(result);
  })
};

module.exports = function(candleSize, _next) {
  next = _.once(_next);

  batcher = new CandleBatcher(candleSize)
    .on('candle', handleBatchedCandles);

  getBatch();
}

const getBatch = () => {
  reader.get(
    iterator.from.unix(),
    iterator.to.unix(),
    'full',
    handleCandles
  )
}

const shiftIterator = () => {
  iterator = {
    from: iterator.from.clone().add(batchSize, 'm'),
    to: iterator.from.clone().add(batchSize * 2, 'm').subtract(1, 's')
  }
}

const handleCandles = (err, data) => {
  if(err) {
    console.error(err);
    util.die('Encountered an error..')
  }

  if(_.size(data) && _.last(data).start >= toUnix || iterator.from.unix() >= toUnix)
    DONE = true;

  batcher.write(data);
  batcher.flush();

  if(DONE) {
    reader.close();

    setTimeout(doneFn, 100);

  } else {
    shiftIterator();
    getBatch();
  }
}

const handleBatchedCandles = candle => {
  result.push(candle);
}


================================================
FILE: core/tools/configBuilder.js
================================================
const fs = require('fs');
const _ = require('lodash');
const toml = require('toml');

const util = require('../util');
const dirs = util.dirs();

const getTOML = function(fileName) {
  var raw = fs.readFileSync(fileName);
  return toml.parse(raw);
}

// build a config object out of a directory of TOML files
module.exports = function() {
  const configDir = util.dirs().config;

  let _config = getTOML(configDir + 'general.toml');
  fs.readdirSync(configDir + 'plugins').forEach(function(pluginFile) {
    let pluginName = _.first(pluginFile.split('.'))
    _config[pluginName] = getTOML(configDir + 'plugins/' + pluginFile);
  });

  // attach the proper adapter
  let adapter = _config.adapter;
  _config[adapter] = getTOML(configDir + 'adapters/' + adapter + '.toml');

  if(_config.tradingAdvisor.enabled) {
    // also load the strat
    let strat = _config.tradingAdvisor.method;
    let stratFile = configDir + 'strategies/' + strat + '.toml';
    if(!fs.existsSync(stratFile))
      util.die('Cannot find the strategy config file for ' + strat);
    _config[strat] = getTOML(stratFile);
  }

  const mode = util.gekkoMode();

  if(mode === 'backtest')
    _config.backtest = getTOML(configDir + 'backtest.toml');

  return _config;
}

================================================
FILE: core/tools/dataStitcher.js
================================================
var _ = require('lodash');
var fs = require('fs');
var moment = require('moment');

var util = require('../util');
var config = util.getConfig();
var dirs = util.dirs();
var log = require(dirs.core + '/log');

var Stitcher = function(batcher) {
  this.batcher = batcher;
}

Stitcher.prototype.ago = function(ts) {
  var now = moment().utc();
  var then = moment.unix(ts).utc();
  return now.diff(then, 'minutes') + ' minutes ago';
}

Stitcher.prototype.verifyExchange = function() {
  require(dirs.gekko + 'exchange/dependencyCheck');
  const exchangeChecker = require(dirs.gekko + 'exchange/exchangeChecker');
  const slug = config.watch.exchange.toLowerCase();
  let exchange;
  try {
    exchange = exchangeChecker.getExchangeCapabilities(slug);
  } catch(e) {
    util.die(e.message);
  }

  if(!exchange)
    util.die(`Unsupported exchange: ${slug}`);

  var error = exchangeChecker.cantMonitor(config.watch);
  if(error)
    util.die(error, true);
}

Stitcher.prototype.prepareHistoricalData = function(done) {
  this.verifyExchange();

  // - step 1: check most recent stored candle window
  // - step 2: check oldest trade reachable by API
  // - step 3: see if overlap
  // - step 4: feed candle stream into CandleBatcher

  if(config.tradingAdvisor.historySize === 0)
    return done();

  var requiredHistory = config.tradingAdvisor.candleSize * config.tradingAdvisor.historySize;
  var Reader = require(dirs.plugins + config.adapter + '/reader');
  
  this.reader = new Reader;

  log.info(
    '\tThe trading method requests',
    requiredHistory,
    'minutes of historic data. Checking availablity..'
  );

  var endTime = moment().utc().startOf('minute');
  var idealStartTime = endTime.clone().subtract(requiredHistory, 'm');
  
  this.reader.mostRecentWindow(idealStartTime, endTime, function(localData) {
    // now we know what data is locally available, what
    // data would we need from the exchange?
    
    if(!localData) {
      log.info('\tNo usable local data available, trying to get as much as possible from the exchange..');
      var idealExchangeStartTime = idealStartTime.clone();
      var idealExchangeStartTimeTS = idealExchangeStartTime.unix();
    }
    else if (idealStartTime.unix() < localData.from) {
      log.info('\tLocal data is still too recent, trying to get as much as possible from the exchange');
      var idealExchangeStartTime = idealStartTime.clone();
      var idealExchangeStartTimeTS = idealExchangeStartTime.unix();
    }
    else {
      log.debug('\tAvailable local data:');
      log.debug('\t\tfrom:', this.ago(localData.from));
      log.debug('\t\tto:', this.ago(localData.to));

      log.info('\tUsable local data available, trying to match with exchange data..')
      // local data is available, we need the next minute


      // make sure we grab back in history far enough
      var secondsOverlap = 60 * 15; // 15 minutes
      var idealExchangeStartTimeTS = localData.to - secondsOverlap;
      var idealExchangeStartTime = moment.unix(idealExchangeStartTimeTS).utc();

      // already set the
      util.setConfigProperty(
        'tradingAdvisor',
        'firstFetchSince',
        idealExchangeStartTimeTS
      );
    }

    // Limit the history Gekko can try to get from the exchange.
    var minutesAgo = endTime.diff(idealExchangeStartTime, 'minutes');
    var maxMinutesAgo = 4 * 60; // 4 hours
    if(minutesAgo > maxMinutesAgo) {
      log.info('\tPreventing Gekko from requesting', minutesAgo, 'minutes of history.');
      idealExchangeStartTime = endTime.clone().subtract(maxMinutesAgo, 'minutes');
      idealExchangeStartTimeTS = idealExchangeStartTime.unix();
    } 

    log.debug('\tFetching exchange data since', this.ago(idealExchangeStartTimeTS))
    this.checkExchangeTrades(idealExchangeStartTime, function(err, exchangeData) {
      log.debug('\tAvailable exchange data:');
      log.debug('\t\tfrom:', this.ago(exchangeData.from));
      log.debug('\t\tto:', this.ago(exchangeData.to));

      // in case we have limited local data, and the
      // exchange would offer more than we have: ignore
      // the local data..
      if(
        localData &&
        exchangeData &&
        exchangeData.from < localData.from
      ) {
        log.debug('\tExchange offered more data than locally available. Ignoring local data');
        localData = false;
      }

      var stitchable = localData && exchangeData.from <= localData.to;
      if(stitchable) {
        log.debug('\tStitching datasets');

        // we can combine local data with exchange data
        if(idealStartTime.unix() >= localData.from) {
          log.info(
            '\tFull history locally available.',
            'Seeding the trading method with all required historical candles.'
          );

        } else {

          // stitchable but not enough

          log.info(
            '\tPartial history locally available, but',
            Math.round((localData.from - idealStartTime.unix()) / 60),
            'minutes are missing.')
          log.info('\tSeeding the trading method with',
            'partial historical data (Gekko needs more time before',
            'it can give advice).'
          );
        }

        // seed all historic data up to the point the exchange can provide.
        var from = localData.from;
        var to = moment.unix(exchangeData.from).utc()
          .startOf('minute')
          .subtract(1, 'minute')
          .unix();

        log.debug('\tSeeding with:');
        log.debug('\t\tfrom:', this.ago(from));
        log.debug('\t\tto:', this.ago(to));
        return this.seedLocalData(from, to, done);

      } else if(!stitchable) {
        log.debug('\tUnable to stitch datasets.')
        // we cannot use any local data..
        log.info(
          '\tNot seeding locally available data to the trading method.'
        );

        if(exchangeData.from < idealExchangeStartTimeTS) {
          log.info('\tHowever the exchange returned enough data anyway!');
        } else if(localData) {
          log.info(
            '\tThe exchange does not return enough data.',
            Math.round((localData.from - idealStartTime.unix()) / 60),
            'minutes are still missing.'
          );
        }
      }

      done();

    }.bind(this));
  }.bind(this));
}

Stitcher.prototype.checkExchangeTrades = function(since, next) {
  var provider = config.watch.exchange.toLowerCase();
  var DataProvider = require(util.dirs().gekko + 'exchange/wrappers/' + provider);

  var exchangeConfig = config.watch;

  // include trader config if trading is enabled
  if (_.isObject(config.trader) && config.trader.enabled) {
    exchangeConfig = _.extend(config.watch, config.trader);
  }

  var watcher = new DataProvider(exchangeConfig);
  watcher.getTrades(since, function(e, d) {
    if(e) {
      util.die(e.message);
    }

    if(_.isEmpty(d))
      return util.die(
        `Gekko tried to retrieve data since ${since.format('YYYY-MM-DD HH:mm:ss')}, however
        ${provider} did not return any trades.`
      );

    next(e, {
      from: _.first(d).date,
      to: _.last(d).date
    })
  });
}

Stitcher.prototype.seedLocalData = function(from, to, next) {
  this.reader.get(from, to, 'full', function(err, rows) {
    rows = _.map(rows, row => {
      row.start = moment.unix(row.start);
      return row;
    });

    this.batcher.write(rows);
    this.batcher.flush();
    this.reader.close();
    next();

  }.bind(this));
}

module.exports = Stitcher;


================================================
FILE: core/tools/dateRangeScanner.js
================================================
var BATCH_SIZE = 60; // minutes
var MISSING_CANDLES_ALLOWED = 3; // minutes, per batch

var _ = require('lodash');
var moment = require('moment');
var async = require('async');

var util = require('../util');
var config = util.getConfig();
var dirs = util.dirs();
var log = require(dirs.core + 'log');

var adapter = config[config.adapter];
var Reader = require(dirs.gekko + adapter.path + '/reader');

var reader = new Reader();

// todo: rewrite with generators or async/await..
var scan = function(done) {
  log.info('Scanning local history for backtestable dateranges.');

  reader.tableExists('candles', (err, exists) => {

    if(err)
      return done(err, null, reader);

    if(!exists)
      return done(null, [], reader);

    async.parallel({
      boundry: reader.getBoundry,
      available: reader.countTotal
    }, (err, res) => {

      var first = res.boundry.first;
      var last = res.boundry.last;

      var optimal = (last - first) / 60;

      log.debug('Available', res.available);
      log.debug('Optimal', optimal);

      // There is a candle for every minute
      if(res.available === optimal + 1) {
        log.info('Gekko is able to fully use the local history.');
        return done(false, [{
          from: first,
          to: last
        }], reader);
      }

      // figure out where the gaps are..

      var missing = optimal - res.available + 1;

      log.info(`The database has ${missing} candles missing, Figuring out which ones...`);
      
      var iterator = {
        from: last - (BATCH_SIZE * 60),
        to: last
      }

      var batches = [];

      // loop through all candles we have
      // in batches and track whether they
      // are complete
      async.whilst(
          () => {
            return iterator.from > first
          },
          next => {
            var from = iterator.from;
            var to = iterator.to;
            reader.count(
              from,
              iterator.to,
              (err, count) => {
                var complete = count + MISSING_CANDLES_ALLOWED > BATCH_SIZE;

                if(complete)
                  batches.push({
                    to: to,
                    from: from
                  });

                next();
              }
            );

            iterator.from -= BATCH_SIZE * 60;
            iterator.to -= BATCH_SIZE * 60;
          },
          () => {
            if(batches.length === 0) {
              return done(null, [], reader);
            }

            // batches is now a list like
            // [ {from: unix, to: unix } ]

            var ranges = [ batches.shift() ];

            _.each(batches, batch => {
              var curRange = _.last(ranges);
              if(batch.to === curRange.from)
                curRange.from = batch.from;
              else
                ranges.push( batch );
            })

            // we have been counting chronologically reversed
            // (backwards, from now into the past), flip definitions
            ranges = ranges.reverse();

            _.map(ranges, r => {
              return {
                from: r.to,
                to: r.from
              }
            });


            // ranges is now a list like
            // [ {from: unix, to: unix } ]
            //
            // it contains all valid dataranges available for the
            // end user.

            return done(false, ranges, reader);
          }
        )
    });

  });
}

module.exports = scan;

================================================
FILE: core/tulind.js
================================================
var semver = require("semver");
var _ = require('lodash');

// validate that talib is installed, if not we'll throw an exception which will
// prevent further loading or out outside this module
try {
    var tulind = require("tulind");
} catch (e) {
    module.exports = null;
    return;
}

var tulindError = 'Gekko was unable to configure Tulip Indicators:\n\t';

// Wrapper that executes a tulip indicator
var execute = function(callback, params) {
    var tulindCallback = function(err, result) {
        if (err) return callback(err);
        var table = {}
        for (var i = 0; i < params.results.length; ++i) {
            table[params.results[i]] = result[i];
        }
        callback(null, table);
    };

    return params.indicator.indicator(params.inputs, params.options, tulindCallback);
}

// Helper that makes sure all required parameters
// for a specific talib indicator are present.
var verifyParams = (methodName, params) => {
    var requiredParams = methods[methodName].requires;

    _.each(requiredParams, paramName => {
        if(!_.has(params, paramName)) {
            throw new Error(tulindError + methodName + ' requires ' + paramName + '.');
        }

        var val = params[paramName];

        if(!_.isNumber(val)) {
            throw new Error(tulindError + paramName + ' needs to be a number');
        }
    });
}

var methods = {};

methods.ad = {
    requires: [],
    create: (params) => {
        verifyParams('ad', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.ad,
            inputs: [data.high, data.low, data.close, data.volume],
            options: [],
            results: ['result'],
        });
    }
}

methods.adosc = {
    requires: ['optInFastPeriod', 'optInSlowPeriod'],
    create: (params) => {
        verifyParams('adosc', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.adosc,
            inputs: [data.high, data.low, data.close, data.volume],
            options: [params.optInFastPeriod, params.optInSlowPeriod],
            results: ['result'],
        });
    }
}

methods.adx = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('adx', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.adx,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.adxr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('adxr', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.adxr,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.ao = {
    requires: [],
    create: (params) => {
        verifyParams('ao', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.ao,
            inputs: [data.high, data.low],
            options: [],
            results: ['result'],
        });
    }
}

methods.apo = {
    requires: ['optInFastPeriod', 'optInSlowPeriod'],
    create: (params) => {
        verifyParams('apo', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.apo,
            inputs: [data.close],
            options: [params.optInFastPeriod, params.optInSlowPeriod],
            results: ['result'],
        });
    }
}

methods.aroon = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('aroon', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.aroon,
            inputs: [data.high, data.low],
            options: [params.optInTimePeriod],
            results: ['aroonDown', 'aroonUp'],
        });
    }
}

methods.aroonosc = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('aroonosc', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.aroonosc,
            inputs: [data.high, data.low],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.atr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('atr', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.atr,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.avgprice = {
    requires: [],
    create: (params) => {
        verifyParams('avgprice', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.avgprice,
            inputs: [data.open, data.high, data.low, data.close],
            options: [],
            results: ['result'],
        });
    }
}

methods.bbands = {
    requires: ['optInTimePeriod', 'optInNbStdDevs'],
    create: (params) => {
        verifyParams('bbands', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.bbands,
            inputs: [data.close],
            options: [params.optInTimePeriod, params.optInNbStdDevs],
            results: ['bbandsLower', 'bbandsMiddle', 'bbandsUpper'],
        });
    }
}

methods.bop = {
    requires: [],
    create: (params) => {
        verifyParams('bop', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.bop,
            inputs: [data.open, data.high, data.low, data.close],
            options: [],
            results: ['result'],
        });
    }
}

methods.cci = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('cci', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.cci,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.cmo = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('cmo', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.cmo,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.cvi = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('cvi', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.cvi,
            inputs: [data.high, data.low],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.dema = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('dema', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.dema,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.di = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('di', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.di,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['diPlus', 'diMinus'],
        });
    }
}

methods.dm = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('dm', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.dm,
            inputs: [data.high, data.low],
            options: [params.optInTimePeriod],
            results: ['dmPlus', 'dmLow'],
        });
    }
}

methods.dpo = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('dpo', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.dpo,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.dx = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('dx', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.dx,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.ema = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('ema', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.ema,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.emv = {
    requires: [],
    create: (params) => {
        verifyParams('emv', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.emv,
            inputs: [data.high, data.low, data.volume],
            options: [params.optInTimePeriod],
            results: [],
        });
    }
}

methods.fisher = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('fisher', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.fisher,
            inputs: [data.high, data.low],
            options: [params.optInTimePeriod],
            results: ['fisher', 'fisherPeriod'],
        });
    }
}

methods.fosc = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('fosc', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.fosc,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.hma = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('hma', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.hma,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.kama = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('kama', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.kama,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.kvo = {
    requires: ['optInFastPeriod', 'optInSlowPeriod'],
    create: (params) => {
        verifyParams('kvo', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.kvo,
            inputs: [data.high, data.low, data.close, data.volume],
            options: [params.optInFastPeriod, params.optInSlowPeriod],
            results: ['result'],
        });
    }
}

methods.linreg = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('linreg', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.linreg,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.linregintercept = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('linregintercept', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.linregintercept,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.linregslope = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('linregslope', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.linregslope,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.macd = {
    requires: ['optInFastPeriod', 'optInSlowPeriod', 'optInSignalPeriod'],
    create: (params) => {
        verifyParams('macd', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.macd,
            inputs: [data.close],
            options: [params.optInFastPeriod, params.optInSlowPeriod, params.optInSignalPeriod],
            results: ['macd', 'macdSignal', 'macdHistogram'],
        });
    }
}

methods.marketfi = {
    requires: [],
    create: (params) => {
        verifyParams('marketfi', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.marketfi,
            inputs: [data.high, data.low, data.volume],
            options: [],
            results: ['result'],
        });
    }
}

methods.mass = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('mass', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.mass,
            inputs: [data.high, data.low],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.medprice = {
    requires: [],
    create: (params) => {
        verifyParams('medprice', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.medprice,
            inputs: [data.high, data.low],
            options: [],
            results: ['result'],
        });
    }
}

methods.mfi = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('mfi', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.mfi,
            inputs: [data.high, data.low, data.close, data.volume],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.msw = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('msw', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.msw,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['mswSine', 'mswLead'],
        });
    }
}

methods.natr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('natr', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.natr,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.nvi = {
    requires: [],
    create: (params) => {
        verifyParams('nvi', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.nvi,
            inputs: [data.close, data.volume],
            options: [],
            results: ['result'],
        });
    }
}

methods.obv = {
    requires: [],
    create: (params) => {
        verifyParams('obv', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.obv,
            inputs: [data.close, data.volume],
            options: [],
            results: ['result'],
        });
    }
}

methods.ppo = {
    requires: ['optInFastPeriod', 'optInSlowPeriod'],
    create: (params) => {
        verifyParams('ppo', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.ppo,
            inputs: [data.close],
            options: [params.optInFastPeriod, params.optInSlowPeriod],
            results: ['result'],
        });
    }
}

methods.psar = {
    requires: ['optInAcceleration', 'optInMaximum'],
    create: (params) => {
        verifyParams('psar', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.psar,
            inputs: [data.high, data.low],
            options: [params.optInAcceleration, params.optInMaximum],
            results: ['result'],
        });
    }
}

methods.pvi = {
    requires: [],
    create: (params) => {
        verifyParams('pvi', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.pvi,
            inputs: [data.close, data.volume],
            options: [],
            results: ['result'],
        });
    }
}

methods.qstick = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('qstick', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.qstick,
            inputs: [data.open, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.roc = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('roc', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.roc,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.rocr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('rocr', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.rocr,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.rsi = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('rsi', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.rsi,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.sma = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('sma', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.sma,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.stddev = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('stddev', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.stddev,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.stoch = {
    requires: ['optInFastKPeriod', 'optInSlowKPeriod', 'optInSlowDPeriod'],
    create: (params) => {
        verifyParams('stoch', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.stoch,
            inputs: [data.high, data.low, data.close],
            options: [params.optInFastKPeriod, params.optInSlowKPeriod, params.optInSlowDPeriod],
            results: ['stochK', 'stochD'],
        });
    }
}

methods.sum = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('sum', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.sum,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.tema = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('tema', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.tema,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.tr = {
    requires: [],
    create: (params) => {
        verifyParams('tr', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.tr,
            inputs: [data.high, data.low, data.close],
            options: [],
            results: ['result'],
        });
    }
}

methods.trima = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('trima', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.trima,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.trix = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('trix', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.trix,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.tsf = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('tsf', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.tsf,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.typprice = {
    requires: [],
    create: (params) => {
        verifyParams('typprice', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.typprice,
            inputs: [data.high, data.low, data.close],
            options: [],
            results: ['result'],
        });
    }
}

methods.ultosc = {
    requires: ['optInTimePeriod1', 'optInTimePeriod2', 'optInTimePeriod3'],
    create: (params) => {
        verifyParams('ultosc', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.ultosc,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod1, params.optInTimePeriod2, params.optInTimePeriod3],
            results: ['result'],
        });
    }
}

methods.vhf = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('vhf', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.vhf,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.vidya = {
    requires: ['optInFastPeriod', 'optInSlowPeriod', 'optInAlpha'],
    create: (params) => {
        verifyParams('vidya', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.vidya,
            inputs: [data.close],
            options: [params.optInFastPeriod, params.optInSlowPeriod, params.optInAlpha],
            results: ['result'],
        });
    }
}

methods.volatility = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('volatility', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.volatility,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.vosc = {
    requires: ['optInFastPeriod', 'optInSlowPeriod'],
    create: (params) => {
        verifyParams('vosc', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.vosc,
            inputs: [data.volume],
            options: [params.optInFastPeriod, params.optInSlowPeriod],
            results: ['result'],
        });
    }
}

methods.vwma = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('vwma', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.vwma,
            inputs: [data.close, data.volume],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.wad = {
    requires: [],
    create: (params) => {
        verifyParams('wad', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.wad,
            inputs: [data.high, data.low, data.close],
            options: [],
            results: ['result'],
        });
    }
}

methods.wcprice = {
    requires: [],
    create: (params) => {
        verifyParams('wcprice', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.wcprice,
            inputs: [data.high, data.low, data.close],
            options: [],
            results: ['result'],
        });
    }
}

methods.wilders = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('wilders', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.wilders,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.willr = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('willr', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.willr,
            inputs: [data.high, data.low, data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.wma = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('wma', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.wma,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

methods.zlema = {
    requires: ['optInTimePeriod'],
    create: (params) => {
        verifyParams('zlema', params);

        return (data, callback) => execute(callback, {
            indicator: tulind.indicators.zlema,
            inputs: [data.close],
            options: [params.optInTimePeriod],
            results: ['result'],
        });
    }
}

module.exports = methods;



================================================
FILE: core/util.js
================================================
var moment = require('moment');
var _ = require('lodash');
var path = require('path');
var fs = require('fs');
var semver = require('semver');
var program = require('commander');

var startTime = moment();

var _config = false;
var _package = false;
var _nodeVersion = false;
var _gekkoMode = false;
var _gekkoEnv = false;

var _args = false;

// helper functions
var util = {
  getConfig: function() {
    // cache
    if(_config)
      return _config;

    if(!program.config)
        util.die('Please specify a config file.', true);

    if(!fs.existsSync(util.dirs().gekko + program.config))
      util.die('Cannot find the specified config file.', true);

    _config = require(util.dirs().gekko + program.config);
    return _config;
  },
  // overwrite the whole config
  setConfig: function(config) {
    _config = config;
  },
  setConfigProperty: function(parent, key, value) {
    if(parent)
      _config[parent][key] = value;
    else
      _config[key] = value;
  },
  getVersion: function() {
    return util.getPackage().version;
  },
  getPackage: function() {
    if(_package)
      return _package;


    _package = JSON.parse( fs.readFileSync(__dirname + '/../package.json', 'utf8') );
    return _package;
  },
  getRequiredNodeVersion: function() {
    return util.getPackage().engines.node;
  },
  recentNode: function() {
    var required = util.getRequiredNodeVersion();
    return semver.satisfies(process.version, required);
  },
  // check if two moments are corresponding
  // to the same time
  equals: function(a, b) {
    return !(a < b || a > b)
  },
  minToMs: function(min) {
    return min * 60 * 1000;
  },
  defer: function(fn) {
    return function(args) {
      var args = _.toArray(arguments);
      return _.defer(function() { fn.apply(this, args) });
    }
  },
  logVersion: function() {
    return  `Gekko version: v${util.getVersion()}`
    + `\nNodejs version: ${process.version}`;
  },
  die: function(m, soft) {

    if(_gekkoEnv === 'child-process') {
      return process.send({type: 'error', error: '\n ERROR: ' + m + '\n'});
    }

    var log = console.log.bind(console);

    if(m) {
      if(soft) {
        log('\n ERROR: ' + m + '\n\n');
      } else {
        log(`\nGekko encountered an error and can\'t continue`);
        log('\nError:\n');
        log(m, '\n\n');
        log('\nMeta debug info:\n');
        log(util.logVersion());
        log('');
      }
    }
    process.exit(1);
  },
  dirs: function() {
    var ROOT = __dirname + '/../';

    return {
      gekko: ROOT,
      core: ROOT + 'core/',
      markets: ROOT + 'core/markets/',
      exchanges: ROOT + 'exchange/wrappers/',
      plugins: ROOT + 'plugins/',
      methods: ROOT + 'strategies/',
      indicators: ROOT + 'strategies/indicators/',
      budfox: ROOT + 'core/budfox/',
      importers: ROOT + 'importers/exchanges/',
      tools: ROOT + 'core/tools/',
      workers: ROOT + 'core/workers/',
      web: ROOT + 'web/',
      config: ROOT + 'config/',
      broker: ROOT + 'exchange/'
    }
  },
  inherit: function(dest, source) {
    require('util').inherits(
      dest,
      source
    );
  },
  makeEventEmitter: function(dest) {
    util.inherit(dest, require('events').EventEmitter);
  },
  setGekkoMode: function(mode) {
    _gekkoMode = mode;
  },
  gekkoMode: function() {
    if(_gekkoMode)
      return _gekkoMode;

    if(program['import'])
      return 'importer';
    else if(program.backtest)
      return 'backtest';
    else
      return 'realtime';
  },
  gekkoModes: function() {
    return [
      'importer',
      'backtest',
      'realtime'
    ]
  },
  setGekkoEnv: function(env) {
    _gekkoEnv = env;
  },
  gekkoEnv: function() {
    return _gekkoEnv || 'standalone';
  },
  launchUI: function() {
    if(program['ui'])
      return true;
    else
      return false;
  },
  getStartTime: function() {
    return startTime;
  },
}

// NOTE: those options are only used
// in stand alone mode
program
  .version(util.logVersion())
  .option('-c, --config <file>', 'Config file')
  .option('-b, --backtest', 'backtesting mode')
  .option('-i, --import', 'importer mode')
  .option('--ui', 'launch a web UI')
  .parse(process.argv);

// make sure the current node version is recent enough
if(!util.recentNode())
  util.die([
    'Your local version of Node.js is too old. ',
    'You have ',
    process.version,
    ' and you need atleast ',
    util.getRequiredNodeVersion()
  ].join(''), true);

module.exports = util;


================================================
FILE: core/workers/datasetScan/parent.js
================================================
var _ = require('lodash');
var moment = require('moment');
var async = require('async');
var os = require('os');

var util = require('../../util');
var dirs = util.dirs();

var dateRangeScan = require('../dateRangeScan/parent');

module.exports = function(config, done) {

  util.setConfig(config);

  var adapter = config[config.adapter];
  var scan = require(dirs.gekko + adapter.path + '/scanner');

  scan((err, markets) => {

    if(err)
      return done(err);

      let numCPUCores = os.cpus().length;
      if(numCPUCores === undefined)
         numCPUCores = 1;
      async.eachLimit(markets, numCPUCores, (market, next) => {

      let marketConfig = _.clone(config);
      marketConfig.watch = market;

      dateRangeScan(marketConfig, (err, ranges) => {
        if(err)
          return next();

        market.ranges = ranges;

        next();
      });

    }, err => {
      let resp = {
        datasets: [],
        errors: []
      }
      markets.forEach(market => {
        if(market.ranges)
          resp.datasets.push(market);
        else
          resp.errors.push(market);
      })
      done(err, resp);
    })
  });
}


================================================
FILE: core/workers/dateRangeScan/child.js
================================================
var util = require(__dirname + '/../../util');

var dirs = util.dirs();
var ipc = require('relieve').IPCEE(process);

ipc.on('start', config => {

  // force correct gekko env
  util.setGekkoEnv('child-process');

  // force disable debug
  config.debug = false;

  // persist config
  util.setConfig(config);

  var scan = require(dirs.tools + 'dateRangeScanner');
  scan(
    (err, ranges, reader) => {
      reader.close();
      ipc.send('ranges', ranges);
      process.exit(0);
    }
  );
});



================================================
FILE: core/workers/dateRangeScan/parent.js
================================================
var ForkTask = require('relieve').tasks.ForkTask;
var fork = require('child_process').fork;

module.exports = function(config, done) {
  var debug = typeof v8debug === 'object';
  if (debug) {
    process.execArgv = [];
  }

  task = new ForkTask(fork(__dirname + '/child'));

  task.send('start', config);

  task.once('ranges', ranges => {
    return done(false, ranges);
  });
  task.on('exit', code => {
    if(code !== 0)
      done('ERROR, unable to scan dateranges, please check the console.');
  });
}


================================================
FILE: core/workers/loadCandles/child.js
================================================
var start = (config, candleSize, daterange) => {
  var util = require(__dirname + '/../../util');

  // force correct gekko env
  util.setGekkoEnv('child-process');

  // force disable debug
  config.debug = false;
  util.setConfig(config);

  var dirs = util.dirs();

  var load = require(dirs.tools + 'candleLoader');
  load(config.candleSize, candles => {
    process.send(candles);
  })
}

process.send('ready');

process.on('message', (m) => {
  if(m.what === 'start')
    start(m.config, m.candleSize, m.daterange);
});

process.on('disconnect', function() {
  process.exit(0);
})


================================================
FILE: core/workers/loadCandles/parent.js
================================================
// example usage:

// let config = {
//   watch: {
//     exchange: 'poloniex',
//     currency: 'USDT',
//     asset: 'BTC'
//   },
//   daterange: {
//     from: '2016-05-22 11:22',
//     to: '2016-06-03 19:56'
//   },
//   adapter: 'sqlite',
//   sqlite: {
//     path: 'plugins/sqlite',

//     dataDirectory: 'history',
//     version: 0.1,

//     dependencies: [{
//       module: 'sqlite3',
//       version: '3.1.4'
//     }]
//   },
//   candleSize: 100
// }

// module.exports(config, function(err, data) {
//   console.log('FINAL CALLBACK');
//   console.log('err', err);
//   console.log('data', data.length);
// })


const fork = require('child_process').fork;
const _ = require('lodash');

module.exports = (config, callback) => {
  var debug = typeof v8debug === 'object';
  if (debug) {
    process.execArgv = [];
  }

  const child = fork(__dirname + '/child');

  const message = {
    what: 'start',
    config
  }

  const done = _.once(callback);

  child.on('message', function(m) {
    if(m === 'ready')
      return child.send(message);

    // else we are done and have candles!
    done(null, m);
    if (this.connected) {
      this.disconnect();
    }
  });

  child.on('exit', code => {
    if(code !== 0)
      done('ERROR, unable to load candles, please check the console.');
  });
}


================================================
FILE: core/workers/pipeline/child.js
================================================
/*

  Gekko is a Bitcoin trading bot for popular Bitcoin exchanges written 
  in node, it features multiple trading methods using technical analysis.

  If you are interested in how Gekko works, read more about Gekko's 
  architecture here:

  https://github.com/askmike/gekko/blob/stable/docs/internals/architecture.md

  Disclaimer:

  USE AT YOUR OWN RISK!

  The author of this project is NOT responsible for any damage or loss caused 
  by this software. There can be bugs and the bot may not perform as expected 
  or specified. Please consider testing it first with paper trading and/or 
  backtesting on historical data. Also look at the code to see what how 
  it is working.

*/

var start = (mode, config) => {
  var util = require(__dirname + '/../../util');

  // force correct gekko env
  util.setGekkoEnv('child-process');

  var dirs = util.dirs();

  // force correct gekko mode & config
  util.setGekkoMode(mode);
  util.setConfig(config);

  var pipeline = require(dirs.core + 'pipeline');
  pipeline({
    config: config,
    mode: mode
  });
}

process.send('ready');

process.on('message', function(m) {
  if(m.what === 'start')
    start(m.mode, m.config);

  if(m.what === 'exit')
    process.exit(0);
});

process.on('disconnect', function() {
  console.log('disconnect');
  process.exit(-1);
})

process
  .on('unhandledRejection', (message, p) => {
    console.error('unhandledRejection', message);
    process.send({type: 'error', message: message});
  })
  .on('uncaughtException', err => {
    console.error('uncaughtException', err);
    process.send({type: 'error', error: err});
    process.exit(1);
  });

================================================
FILE: core/workers/pipeline/messageHandlers/backtestHandler.js
================================================
// Relay the backtest message it when it comes in.

module.exports = done => {
  let backtest;

  return {
    message: message => {
      if(message.type === 'error') {
        done(message.error);
      }

      if(message.backtest) {
        done(null, message.backtest);
      }
    },
    exit: status => {
      if(status !== 0) {
        if(backtest)
          console.error('Child process died after finishing backtest');
        else
          done('Child process has died.');
      }
    }
  }
}

================================================
FILE: core/workers/pipeline/messageHandlers/importerHandler.js
================================================
module.exports = cb => {

  return {
    message: message => {

      if(message.event === 'marketUpdate')
        cb(null, {
          done: false,
          latest: message.payload
        })

      else if(message.type === 'error') {
        cb(message.error);
      }

      else if(message.type === 'log')
        console.log(message.log);
    },
    exit: status => {
      if(status !== 0)
        return cb('Child process has died.');
      else
        cb(null, { done: true });
    }
  }
}

================================================
FILE: core/workers/pipeline/messageHandlers/realtimeHandler.js
================================================
// pass back all messages as is
// (except for errors and logs)

module.exports = cb => {

  return {
    message: message => {

      if(message.type === 'error') {
        cb(message.error);
      }

      else
        cb(null, message);

    },
    exit: status => {
      if(status !== 0)
        cb('Child process has died.');
      else
        cb(null, { done: true });
    }
  }
}

================================================
FILE: core/workers/pipeline/parent.js
================================================
var fork = require('child_process').fork;

module.exports = (mode, config, callback) => {
  var debug = typeof v8debug === 'object';
  if (debug) {
    process.execArgv = [];
  }

  var child = fork(__dirname + '/child');

  // How we should handle client messages depends
  // on the mode of the Pipeline that is being ran.
  var handle = require('./messageHandlers/' + mode + 'Handler')(callback);

  var message = {
    what: 'start',
    mode: mode,
    config: config
  };

  child.on('message', function(m) {
    if(m === 'ready')
      return child.send(message);

    if(m === 'done')
      return child.send({what: 'exit'});

    handle.message(m);
  });

  child.on('exit', handle.exit);

  return child;
}


================================================
FILE: docker-compose.yml
================================================
version: '3'
services:
  gekko:
    build: ./
    volumes:
      - ./volumes/gekko/history:/usr/src/app/history
      - ./config.js:/usr/src/app/config.js
    links:
      - redis
#      - postgresql
    environment:
     - HOST
     - PORT
     - USE_SSL
    ports: # you can comment this out when using the nginx frontend
      - "${PORT}:${PORT}"
## optionally set nginx vars if you wish to frontend it with nginx
#    environment:
#     - VIRTUAL_HOST=gekko
#     - PORT=3000
#     - DOMAIN=gekko

  redis:
    image: redis:latest
    volumes:
      - ./volumes/redis:/data
## optionally uncomment if you wish to use nginx as a frontend
#  nginx:
#    restart: always
#    image: jwilder/nginx-proxy
#    ports:
#     - "80:80"
#    volumes:
#     - /var/run/docker.sock:/tmp/docker.sock:ro
## optionally uncomment if you wish to use postgresql as a db
#  postgresql:
#    restart: always
#    image: postgres:9.6-alpine
#    ports:
#      - 5432:5432
#    volumes:
#      - ./_postgresql:/var/lib/postgresql/data:rw
#    environment:
#      POSTGRES_DB: gekko
#      POSTGRES_USER: username
#      POSTGRES_PASSWORD: password


================================================
FILE: docker-entrypoint.sh
================================================
#!/bin/bash

sed -i 's/127.0.0.1/0.0.0.0/g' /usr/src/app/web/vue/dist/UIconfig.js
sed -i 's/localhost/'${HOST}'/g' /usr/src/app/web/vue/dist/UIconfig.js
sed -i 's/3000/'${PORT}'/g' /usr/src/app/web/vue/dist/UIconfig.js
if [[ "${USE_SSL:-0}" == "1" ]] ; then
    sed -i 's/ssl: false/ssl: true/g' /usr/src/app/web/vue/dist/UIconfig.js
fi
exec node gekko "$@"


================================================
FILE: docs/commandline/Importing.md
================================================
# Importing

*Note: this documentation was written for running Gekko via the command line. If you are using the UI you can simply use the importer under the "local data" tab.*

If you want to use Gekko to [backtest against historical data](./backtesting.md), you most likely need some historical data to test against. Gekko comes with the functionality to automatically import historical data from some exchanges. However, only a few exchanges support this. You can find out with which exchanges Gekko is able to do this [here](https://github.com/askmike/gekko#supported-exchanges).

## Setup

For importing you should [enable and configure](./plugins.md) the following plugin:

 - candleWriter (to store the imported data in a database)

Besides that, make sure to configure `config.watch` properly.

## Configure

In your config set the `importer.daterange` properties to the daterange you would like to import.

## Run

    node gekko --config config.js --import

The result will be something like this:

    2016-06-26 09:12:16 (INFO): Gekko v0.2.2 started
    2016-06-26 09:12:16 (INFO): I'm gonna make you rich, Bud Fox. 

    2016-06-26 09:12:17 (INFO): Setting up Gekko in importer mode
    2016-06-26 09:12:17 (INFO): 
    2016-06-26 09:12:17 (INFO): Setting up:
    2016-06-26 09:12:17 (INFO):      Candle writer
    2016-06-26 09:12:17 (INFO):      Store candles in a database
    2016-06-26 09:12:17 (INFO): 

    2016-06-26 09:12:17 (WARN): The plugin Trading Advisor does not support the mode importer. It has been disabled.
    2016-06-26 09:12:17 (WARN): The plugin Advice logger does not support the mode importer. It has been disabled.
    2016-06-26 09:12:17 (WARN): The plugin Profit Simulator does not support the mode importer. It has been disabled.
    2016-06-26 09:12:18 (DEBUG):    Processing 798 new trades.
    2016-06-26 09:12:18 (DEBUG):    From 2015-09-09 12:00:04 UTC to 2015-09-09 13:58:55 UTC. (2 hours)
    2016-06-26 09:12:20 (DEBUG):    Processing 211 new trades.
    (...)


================================================
FILE: docs/commandline/about_the_commandline.md
================================================
# About the commandline

You don't have to use the UI to control Gekko, you can also use the commandline if you don't have access to a window manager or browser (on a server for example, or anything else you want to SSH into). This is only recommended for advanced users who feel comfortable editing config files and running shell commands.

Using the commandline you run one Gekko instance per command, eg. if you want to import 3 markets you need to run Gekko 3 times.

## Configuring Gekko

If you decide you want to run gekko over the commandline you need to decide two things:

1. What market / settings are you interested in?
2. What should Gekko do? This is either backtest, import or run live.

For the first one you configure a config file: copy `gekko/sample-config.js` to something else (for example `gekko/config.js`). Configure the plugins to your liking. What plugins you need to enable does depend on the answer of question 2. Check the documentation under commandline for that feature.

## Running Gekko

For live mode run:

    node gekko --config config.js

To backtesting run:

    node gekko --config config.js --backtest

To import run:

    node gekko --config config.js --import

================================================
FILE: docs/commandline/backtesting.md
================================================
# Backtesting with Gekko

*Note: this documentation was written for running Gekko via the command line. If you are using the UI you can simply use the importer under the "local data" tab.*

Gekko is able to backtest strategies against historical data.

## Setup

For backtesting you should [enable and configure](./plugins.md) the following plugins:

 - trading advisor (to run your strategy).
 - paper trader (to execute simulated trades).
 - performance analyzer (to calculate how succesfull the strategy would have been).

Besides that, make sure to configure `config.watch`.

## Historical data

Gekko requires historical data to backtest strategies against. The easiest way to get this is to let Gekko import historical data, however this is not supported by a lot of exchanges (see [here](https://github.com/askmike/gekko#supported-exchanges)). The second easiest and most universal way is to run Gekko on real markets using the UI (or alternatively via the commandline with the plugin sqliteWriter enabled). Though this takes a while, as you need to run Gekko for a week to have a week of data.

## Configure

In your config set the `backtest.daterange` to `scan`. This will force Gekko to scan the local database to figure out what dataranges are available. If you already know exactly what daterange you would like to backtest against, you can set the `backtest.daterange` directly (set `backtest.daterange` as an object with the keys `from` and `to` and the values as a data parsable by [moment](http://momentjs.com/docs/#/parsing/)).

## Run

    node gekko --config config.js --backtest

The result will be something like this:

    2016-06-11 08:53:20 (INFO): Gekko v0.2.1 started
    2016-06-11 08:53:20 (INFO): I'm gonna make you rich, Bud Fox.

    2016-06-11 08:53:20 (INFO): Setting up Gekko in backtest mode
    2016-06-11 08:53:20 (INFO):
    2016-06-11 08:53:20 (WARN): The plugin SQLite Datastore does not support the mode backtest. It has been disabled.
    2016-06-11 08:53:20 (INFO): Setting up:
    2016-06-11 08:53:20 (INFO):    Trading Advisor
    2016-06-11 08:53:20 (INFO):    Calculate trading advice
    2016-06-11 08:53:20 (INFO):    Using the trading method: DEMA
    2016-06-11 08:53:20 (INFO):

    2016-06-11 08:53:20 (INFO): Setting up:
    2016-06-11 08:53:20 (INFO):    Profit Simulator
    2016-06-11 08:53:20 (INFO):    Paper trader that logs fake profits.
    2016-06-11 08:53:20 (INFO):

    2016-06-11 08:58:20 (INFO): Profit simulator got advice to long @ 2016-05-30 04:37:00, buying 1.1880062 BTC
    2016-06-11 08:58:21 (INFO): Profit simulator got advice to short  @ 2016-05-31 21:37:00, selling 1.1880062 BTC
    2016-06-11 08:58:21 (INFO): Profit simulator got advice to long @ 2016-06-01 12:37:00, buying 1.14506098 BTC
    2016-06-11 08:58:21 (INFO): Profit simulator got advice to short  @ 2016-06-02 14:57:00, selling 1.14506098 BTC
    2016-06-11 08:58:21 (INFO): Profit simulator got advice to long @ 2016-06-02 23:37:00, buying 1.11711818 BTC
    2016-06-11 08:58:21 (INFO): Profit simulator got advice to short  @ 2016-06-05 12:57:00, selling 1.11711818 BTC
    2016-06-11 08:58:21 (INFO): Profit simulator got advice to long @ 2016-06-06 02:37:00, buying 1.08456953 BTC
    2016-06-11 08:58:22 (INFO): Profit simulator got advice to short  @ 2016-06-07 17:17:00, selling 1.08456953 BTC
    2016-06-11 08:58:22 (INFO): Profit simulator got advice to long @ 2016-06-08 13:17:00, buying 1.05481755 BTC
    2016-06-11 08:58:22 (INFO): Profit simulator got advice to short  @ 2016-06-09 14:17:00, selling 1.05481755 BTC

    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) start time:      2016-05-29 23:34:00
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) end time:      2016-06-10 08:56:00
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) timespan:      11 days days

    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) start price:       516.19
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) end price:       578.97
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) Buy and Hold profit:     12.162189999999995%

    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) amount of trades:    10
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) original simulated balance:  616.19000 USD
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) current simulated balance:   602.59867 USD
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) simulated profit:    -13.59133 USD (-2.20570%)
    2016-06-11 08:53:22 (INFO): (PROFIT REPORT) simulated yearly profit:   -435.53244 USD (-70.68152%)


================================================
FILE: docs/commandline/plugins.md
================================================
## Enabling plugins

*Note: this documentation was written for running Gekko via the command line. If you are using the UI you do not have to manually select plugins.*

Gekko currently has a couple plugins:

- trading advisor (run a TA strategy against a market)
- trader (execute advice from the TA strategy on a real exchange)
- advice logger
- paper trader
- Mailer
- IRC bot
- Campfire bot
- Redis beacon
- XMP Bot
- and more..

To configure a plugin, open up your `config.js` file with a text editor and configure the appropiate section.

## Trading Advisor

If you want Gekko to provide automated trading advice you need to configure this in Gekko. Note that this is a different plugin than the  "trader" which is a responsible for actually creating orders based on this advice. (So if you want automated trading you need both this advice as well as the auto trader).

Documentation about strategies in Gekko can be found [here](../strategies/introduction.md).

### Trader

This plugin automatically creates orders based on the advice from the "Trading Advisor" from the market Gekko is watching. This turns Gekko into an automated trading bot.

Before Gekko can automatically trade you need to create API keys so that Gekko has the rights to create orders on your behalf, the rights Gekko needs are (naming differs per exchange): get info, get balance/portfolio, get open orders, get fee, buy, sell and cancel order. For all exchanges you need the API key and the API secret, for both Bitstamp and CEX.io you also need your username (which is a number at Bitstamp).

Configure it like this:

    config.trader = {
      enabled: true,
      key: 'your-api-key',
      secret: 'your-api-secret',
      username: 'your-username' // your username, only fill in when using bitstamp or cexio
    }

- enabled indicates whether this is on or off.
- key is your API key.
- secret is your API secret.
- username is the username (only required for CEX.io and Bitstamp).

### Advice logger

The advice logger is a small plugin that logs new advice calculated by Gekko as soon as there is any. Go to the config and configure it like this:

    config.adviceLogger = {
      enabled: true
    }

- enabled indicates whether this is on or off.

The advice logged advice will look something like this in the terminal:

    2014-01-15 14:31:44 (INFO): We have new trading advice!
    2014-01-15 14:31:44 (INFO):    Position to take: long
    2014-01-15 14:31:44 (INFO):    Market price: 5.96
    2014-01-15 14:31:44 (INFO):    Based on market time: 2014-01-15 14:31:01

### Paper trader

The paper trader listens to Gekko's advice and on a sell it will swap all (simulated) currency into (simulated) assets at the current price. On a buy it will be the other way around.

Go to the config and configure it like this:

    // do you want Gekko to calculate the profit of its own advice?
    config.paperTrader = {
      enabled: true,
      // report the profit in the currency or the asset?
      reportInCurrency: true,
      // start balance, on what the current balance is compared with
      simulationBalance: {
        // these are in the unit types configured in the watcher.
        asset: 1,
        currency: 100
      },
      // only want report after a sell? set to `false`.
      verbose: false,
      // how much fee in % does each trade cost?
      feeMaker: 0.5,
      feeTaker: 0.6,
      // Using taker or maker fee?
      feeUsing: 'maker',
      // how much slippage should Gekko assume per trade?
      slippage: 0.1
    }

- enabled indicates whether this is on or off.
- reportInCurrency tells Gekko whether it should report in asset or in the currency.
- simulationBalance tells Gekko with what balance it should start.
- verbose specifies how often Gekko should log the results (false is after every trade, true is after every candle).
- fee is the exchange fee (in %) Gekko should take into consideration when simulating orders.
- slippage is the costs in (in %) associated with not being able to buy / sell at market price.*

*If you are trading a lot and you are buying 100% currency you might not get it all at market price and you have to walk the book in order to take that position. Also note that Gekko uses the candle close price and is unaware of the top asks bids, also take this into account. It is important that you set this number correctly or the resulted calculated profit be very wrong. Read more information [here](http://www.investopedia.com/terms/s/slippage.asp). Take these into consideration when setting a slippage:

- How much spread is there normally on this market?
- How thick is the top of the book normally?
- How volatile is this market (the more volatility the bigger the chance you will not get the price you expected)?

The output will be something like:

    2013-06-02 18:21:15 (INFO): ADVICE is to SHORT @ 117.465 (0.132)
    2013-06-02 18:21:15 (INFO): (PROFIT REPORT) original balance:    207.465 USD
    2013-06-02 18:21:15 (INFO): (PROFIT REPORT) current balance:     217.465 USD
    2013-06-02 18:21:15 (INFO): (PROFIT REPORT) profit:          10.000 USD (4.820%)

### Mailer

Mailer will automatically email you whenever Gekko has a new advice.

    // want Gekko to send a mail on buy or sell advice?
    config.mailer = {
      enabled: false,       // Send Emails if true, false to turn off
      sendMailOnStart: true,    // Send 'Gekko starting' message if true, not if false

      Email: 'me@gmail.com',    // Your GMail address

      // You don't have to set your password here, if you leave it blank we will ask it
      // when Gekko's starts.
      //
      // NOTE: Gekko is an open source project < https://github.com/askmike/gekko >,
      // make sure you looked at the code or trust the maintainer of this bot when you
      // fill in your email and password.
      //
      // WARNING: If you have NOT downloaded Gekko from the github page above we CANNOT
      // guarantee that your email address & password are safe!

      password: '',       // Your GMail Password - if not supplied Gekko will prompt on startup.
      tag: '[GEKKO] '      // Prefix all EMail subject lines with this
    }

- enabled indicates whether this is on or off.
- sendMailOnStart will email you right away after Gekko started, you can also use this if you are automatically restarting Gekko to see crash behaviour.
- Email is your email address from which Gekko will send emails (to the same address).
- password is the email password: Gekko needs to login to your account to send emails to you:

  > You don't have to set your password here, if you leave it blank we will ask it
  > when Gekko's starts.
  >
  > NOTE: Gekko is an open source project < https://github.com/askmike/gekko >,
  > make sure you looked at the code or trust the maintainer of this bot when you
  > fill in your email and password.
  >
  > WARNING: If you have NOT downloaded Gekko from the github page above we CANNOT
  > guarantee that your email address & password are safe!

- tag is some text that Gekko will put in all subject lines so you can easily group all advices together.

### IRC bot

IRC bot is a small plugin that connects Gekko to an IRC channel and lets users interact with it using basic commands.

    config.ircbot = {
      enabled: false,
      emitUpdates: false,
      channel: '#your-channel',
      server: 'irc.freenode.net',
      botName: 'gekkobot'
    }

- enabled indicates whether this is on or off.
- emitUpdates tells Gekko that whenever there is a new advice it should broadcast this in the channel.
- channel is the IRC channel the bot will connect to.
- server is the IRC server.
- botName is the username Gekko will use.

### Campfire bot

Campfire bot is a small plugin that connects Gekko to a Campfire room and lets users interact with it using basic commands.

    config.campfire = {
      enabled: false,
      emitUpdates: false,
      nickname: 'Gordon',
      roomId: 673783,
      apiKey: 'e3b0c44298fc1c149afbf4c8996',
      account: 'your-subdomain'
    }

- enabled indicates whether this is on or off.
- emitUpdates tells Gekko that whenever there is a new advice it should broadcast this in the room.
- roomId is the ID of the Campfire room the bot will connect to.
- apiKey is the API key for the Campfire user Gekko will connect using.
- account is the subdomain for the account that the room belongs to.

### Redis beacon

This is an advanced plugin only for programmers! If you are interested in this read more [here](https://github.com/askmike/gekko/blob/stable/docs/internals/plugins.md#redis-beacon).

    config.redisBeacon = {
      enabled: false,
      port: 6379, // redis default
      host: '127.0.0.1', // localhost
        // On default Gekko broadcasts
        // events in the channel with
        // the name of the event, set
        // an optional prefix to the
        // channel name.
      channelPrefix: '',
      broadcast: [
        'small candle'
      ]
    }

- enabled indicates whether this is on or off.
- port is the port redis is running on.
- host is the redis host.
- channelPrefix a string that Gekko will prefix all candles with.
- broadcast is a list of all events you want Gekko to publish.



================================================
FILE: docs/commandline/tradebot.md
================================================
# Tradebot

You can set Gekko up as a tradebot, this will instruct Gekko to:

- Watch a live market.
- Run a strategy (in semi-realtime) over live market data.
- Automatically create buy/sell orders based on signals coming from the strategy.

*As with everything in Gekko, the tradebot will make decisions based on the strategy selected/configured/created **by YOU**. If you end up losing money, you have no one to blame but yourself.*

## Configuration

First, set up Gekko for commandline usage (see [this document](./about_the_commandline.md) for details). After that, configure the following plugins:

- `config.watch` - the market to trade on.
- `candleWriter` - (optional) also store market data to disk.
- `tradingAdvisor` - configure the strategy and candle properties.
- `trader` - configure Gekko access to your exchange account.
- `performanceAnalyzer` - enable.

Turn off the paperTrader (there can only be 1 trade plugin active per instance).

Once done, run Gekko like so:

    node gekko --config your-config-file.js


================================================
FILE: docs/extending/add_a_plugin.md
================================================
# Plugins

A plugin is a low level module or plugin that can act upon events bubbling
through Gekko. If you want to have custom functionality so that your rocket
flies to the moon as soon as the price hits X you should create a plugin for it.

All plugins live in `gekko/plugins`.

Note that in order to use custom plugins, you have to run Gekko over [the commandline](../commandline/about_the_commandline.md).

## Existing plugins:

- Candle Store: save trades to disk.
- Mailer: mail trading advice to your gmail account.
- Pushbu
Download .txt
gitextract_1c3mqyr_/

├── .dockerignore
├── .editorconfig
├── .github/
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── stale.yml
├── .gitignore
├── .prettierrc
├── .travis.yml
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── appveyor.yml
├── config/
│   ├── adapters/
│   │   ├── mongodb.toml
│   │   ├── postgresql.toml
│   │   └── sqlite.toml
│   ├── backtest.toml
│   ├── general.toml
│   ├── plugins/
│   │   ├── candleWriter.toml
│   │   ├── paperTrader.toml
│   │   ├── performanceAnalyzer.toml
│   │   ├── pushbullet.toml
│   │   ├── trader.toml
│   │   └── tradingAdvisor.toml
│   └── strategies/
│       ├── CCI.toml
│       ├── DEMA.toml
│       ├── MACD.toml
│       ├── PPO.toml
│       ├── RSI.toml
│       ├── StochRSI.toml
│       ├── TMA.toml
│       ├── TSI.toml
│       ├── UO.toml
│       ├── custom.toml
│       ├── talib-macd.toml
│       ├── tulip-adx.toml
│       ├── tulip-macd.toml
│       ├── tulip-multi-strat.toml
│       └── varPPO.toml
├── core/
│   ├── budfox/
│   │   ├── budfox.js
│   │   ├── candleCreator.js
│   │   ├── candleManager.js
│   │   ├── heart.js
│   │   ├── marketDataProvider.js
│   │   ├── marketFetcher.js
│   │   └── tradeBatcher.js
│   ├── candleBatcher.js
│   ├── emitter.js
│   ├── gekkoStream.js
│   ├── log.js
│   ├── markets/
│   │   ├── backtest.js
│   │   ├── importer.js
│   │   ├── leech.js
│   │   └── realtime.js
│   ├── pipeline.js
│   ├── pluginUtil.js
│   ├── prepareDateRange.js
│   ├── stats.js
│   ├── talib.js
│   ├── tools/
│   │   ├── candleLoader.js
│   │   ├── configBuilder.js
│   │   ├── dataStitcher.js
│   │   └── dateRangeScanner.js
│   ├── tulind.js
│   ├── util.js
│   └── workers/
│       ├── datasetScan/
│       │   └── parent.js
│       ├── dateRangeScan/
│       │   ├── child.js
│       │   └── parent.js
│       ├── loadCandles/
│       │   ├── child.js
│       │   └── parent.js
│       └── pipeline/
│           ├── child.js
│           ├── messageHandlers/
│           │   ├── backtestHandler.js
│           │   ├── importerHandler.js
│           │   └── realtimeHandler.js
│           └── parent.js
├── docker-compose.yml
├── docker-entrypoint.sh
├── docs/
│   ├── commandline/
│   │   ├── Importing.md
│   │   ├── about_the_commandline.md
│   │   ├── backtesting.md
│   │   ├── plugins.md
│   │   └── tradebot.md
│   ├── extending/
│   │   ├── add_a_plugin.md
│   │   ├── add_an_exchange.md
│   │   └── other_software.md
│   ├── features/
│   │   ├── backtesting.md
│   │   ├── importing.md
│   │   ├── paper_trading.md
│   │   └── trading_bot.md
│   ├── gekko-broker/
│   │   ├── introduction.md
│   │   ├── sticky_order.md
│   │   └── wrapper_api.md
│   ├── installation/
│   │   ├── configuring_gekko_on_a_server.md
│   │   ├── installing_gekko.md
│   │   ├── installing_gekko_on_raspberry_pi_2_or_3.md
│   │   ├── installing_gekko_on_windows.md
│   │   ├── installing_gekko_on_windows_with_bash_on_windows_10.md
│   │   ├── installing_gekko_using_docker.md
│   │   └── updating_gekko.md
│   ├── internals/
│   │   ├── architecture.md
│   │   ├── budfox.md
│   │   ├── events.md
│   │   ├── gekko_ui.md
│   │   ├── plugins.md
│   │   └── server_api.md
│   ├── introduction/
│   │   ├── about_gekko.md
│   │   ├── getting_help.md
│   │   ├── roadmap.md
│   │   ├── scope.md
│   │   ├── supported_exchanges.md
│   │   └── supporting_the_project.md
│   └── strategies/
│       ├── creating_a_strategy.md
│       ├── gekko_indicators.md
│       ├── introduction.md
│       ├── talib_indicators.md
│       └── tulip_indicators.md
├── exchange/
│   ├── .npmignore
│   ├── README.md
│   ├── dependencyCheck.js
│   ├── exchangeChecker.js
│   ├── exchangeErrors.js
│   ├── exchangeUtils.js
│   ├── gekkoBroker.js
│   ├── orders/
│   │   ├── index.js
│   │   ├── limit.js
│   │   ├── order.js
│   │   ├── states.js
│   │   └── sticky.js
│   ├── package.json
│   ├── portfolioManager.js
│   ├── trigger.js
│   ├── triggers/
│   │   ├── index.js
│   │   └── trailingStop.js
│   ├── util/
│   │   └── genMarketFiles/
│   │       ├── update-binance.js
│   │       ├── update-bitfinex.js
│   │       ├── update-coinbase.js
│   │       ├── update-coinfalcon.js
│   │       └── update-kraken.js
│   └── wrappers/
│       ├── DEBUG_exchange-simulator.js
│       ├── binance-markets.json
│       ├── binance.js
│       ├── bitcoin-co-id.js.old
│       ├── bitfinex-markets.json
│       ├── bitfinex.js
│       ├── bitfinex_v2.js.prep
│       ├── bitstamp.js.old
│       ├── bittrex.js
│       ├── btc-markets.js.old
│       ├── btcc.js.old
│       ├── bx.in.th.js.old
│       ├── cexio.js.old
│       ├── coinbase-markets.json
│       ├── coinfalcon-markets.json
│       ├── coinfalcon.js
│       ├── coingi.js
│       ├── exmo-markets.json
│       ├── exmo.js
│       ├── gdax.js
│       ├── gemini.js.old
│       ├── kraken-markets.json
│       ├── kraken.js
│       ├── lakebtc.js
│       ├── luno.js
│       ├── mexbt.js.old
│       ├── mtgox.js.old
│       ├── okcoin.js.old
│       ├── poloniex-markets.json
│       ├── poloniex.js
│       ├── quadriga-markets.json
│       ├── quadriga.js.old
│       ├── therocktrading-markets.json
│       ├── therocktrading.js
│       ├── wex.nz.js.old
│       └── zaif.jp.js.old
├── gekko.js
├── importers/
│   └── exchanges/
│       ├── binance.js
│       ├── bitfinex.js
│       ├── btcc.js
│       ├── coinfalcon.js
│       ├── gdax.js
│       ├── kraken.js
│       ├── luno.js
│       ├── poloniex.js
│       └── therocktrading.js
├── logs/
│   └── .gitignore
├── package.json
├── plugins/
│   ├── adviceLogger.js
│   ├── backtestResultExporter.js
│   ├── blotter.js
│   ├── campfire.js
│   ├── candleUploader.js
│   ├── childToParent.js
│   ├── eventLogger.js
│   ├── ifttt.js
│   ├── ircbot.js
│   ├── kodi.js
│   ├── mailer.js
│   ├── mongodb/
│   │   ├── handle.js
│   │   ├── reader.js
│   │   ├── scanner.js
│   │   ├── util.js
│   │   └── writer.js
│   ├── paperTrader/
│   │   └── paperTrader.js
│   ├── performanceAnalyzer/
│   │   ├── logger.js
│   │   └── performanceAnalyzer.js
│   ├── postgresql/
│   │   ├── handle.js
│   │   ├── reader.js
│   │   ├── scanner.js
│   │   ├── util.js
│   │   └── writer.js
│   ├── pushbullet.js
│   ├── pushover.js
│   ├── redisBeacon.js
│   ├── slack.js
│   ├── sqlite/
│   │   ├── handle.js
│   │   ├── reader.js
│   │   ├── scanner.js
│   │   ├── util.js
│   │   └── writer.js
│   ├── telegrambot.js
│   ├── trader/
│   │   └── trader.js
│   ├── tradingAdvisor/
│   │   ├── asyncIndicatorRunner.js
│   │   ├── baseTradingMethod.js
│   │   └── tradingAdvisor.js
│   ├── twitter.js
│   ├── webserver.js
│   └── xmppbot.js
├── plugins.js
├── sample-config.js
├── strategies/
│   ├── CCI.js
│   ├── DEBUG_single-advice.js
│   ├── DEBUG_toggle-advice.js
│   ├── DEMA.js
│   ├── MACD.js
│   ├── PPO.js
│   ├── RSI.js
│   ├── StochRSI.js
│   ├── TMA.js
│   ├── TSI.js
│   ├── UO.js
│   ├── custom.js
│   ├── indicators/
│   │   ├── CCI.js
│   │   ├── DEMA.js
│   │   ├── EMA.js
│   │   ├── LRC.js
│   │   ├── MACD.js
│   │   ├── PPO.js
│   │   ├── RSI.js
│   │   ├── SMA.js
│   │   ├── SMMA.js
│   │   ├── TSI.js
│   │   └── UO.js
│   ├── noop.js
│   ├── talib-macd.js
│   ├── tulip-adx.js
│   ├── tulip-macd.js
│   ├── tulip-multi-strat.js
│   └── varPPO.js
├── subscriptions.js
├── test/
│   ├── _prepare.js
│   ├── candleBatcher.js
│   ├── exchanges/
│   │   ├── bitstamp.js
│   │   └── data/
│   │       └── bitstamp_trades.json
│   ├── indicators/
│   │   ├── cci.js
│   │   ├── dema.js
│   │   ├── ema.js
│   │   ├── macd.js
│   │   ├── ppo.js
│   │   ├── rsi.js
│   │   ├── sma.js
│   │   └── smma.js
│   ├── marketFetcher.js
│   ├── plugins/
│   │   └── portfolioManager.js
│   ├── test-config.json
│   ├── tradeBatcher.js
│   └── triggers/
│       └── trailingStop.js
└── web/
    ├── apiKeyManager.js
    ├── baseUIconfig.js
    ├── isWindows.js
    ├── routes/
    │   ├── apiKeys.js
    │   ├── backtest.js
    │   ├── baseConfig.js
    │   ├── configPart.js
    │   ├── deleteGekko.js
    │   ├── exchanges.js
    │   ├── getCandles.js
    │   ├── import.js
    │   ├── info.js
    │   ├── list.js
    │   ├── scanDatasets.js
    │   ├── scanDateRange.js
    │   ├── startGekko.js
    │   ├── stopGekko.js
    │   └── strategies.js
    ├── server.js
    ├── state/
    │   ├── cache.js
    │   ├── gekkoManager.js
    │   ├── listManager.js
    │   ├── logger.js
    │   └── reduceState.js
    └── vue/
        ├── babel.config.js
        ├── dist/
        │   ├── UIconfig.js
        │   ├── app.5e99ecf7.js
        │   ├── app.730569ff.css
        │   ├── chunk-vendors.b9a11975.js
        │   ├── index.html
        │   └── vendor/
        │       ├── d3.js
        │       ├── humanize-duration.js
        │       ├── moment.js
        │       └── toml.js
        ├── package.json
        ├── public/
        │   ├── UIconfig.js
        │   ├── index.html
        │   └── vendor/
        │       ├── d3.js
        │       ├── humanize-duration.js
        │       ├── moment.js
        │       └── toml.js
        ├── src/
        │   ├── App.vue
        │   ├── components/
        │   │   ├── backtester/
        │   │   │   ├── backtestConfigBuilder.vue
        │   │   │   ├── backtester.vue
        │   │   │   └── result/
        │   │   │       ├── chartWrapper.vue
        │   │   │       ├── result.vue
        │   │   │       ├── roundtripTable.vue
        │   │   │       └── summary.vue
        │   │   ├── config/
        │   │   │   ├── apiConfigBuilder.vue
        │   │   │   └── config.vue
        │   │   ├── data/
        │   │   │   ├── data.vue
        │   │   │   └── import/
        │   │   │       ├── importConfigBuilder.vue
        │   │   │       ├── importer.vue
        │   │   │       └── single.vue
        │   │   ├── gekko/
        │   │   │   ├── gekkoConfigBuilder.vue
        │   │   │   ├── list.vue
        │   │   │   ├── new.vue
        │   │   │   ├── singleGekko.vue
        │   │   │   └── singleWatcher.vue
        │   │   ├── global/
        │   │   │   ├── blockSpinner.vue
        │   │   │   ├── configbuilder/
        │   │   │   │   ├── datasetpicker.vue
        │   │   │   │   ├── exchangepicker.vue
        │   │   │   │   ├── marketpicker.vue
        │   │   │   │   ├── papertrader.vue
        │   │   │   │   ├── rangecreator.vue
        │   │   │   │   ├── rangepicker.vue
        │   │   │   │   ├── stratpicker.vue
        │   │   │   │   └── typepicker.vue
        │   │   │   ├── mixins/
        │   │   │   │   └── dataset.js
        │   │   │   ├── paperTradeSummary.vue
        │   │   │   ├── progressBar.vue
        │   │   │   └── ws.js
        │   │   └── layout/
        │   │       ├── footer.vue
        │   │       ├── header.vue
        │   │       ├── home.vue
        │   │       └── modal.vue
        │   ├── d3/
        │   │   ├── chart3.js
        │   │   ├── chart4.js
        │   │   └── message.js
        │   ├── main.js
        │   ├── store/
        │   │   ├── index.js
        │   │   ├── init.js
        │   │   └── modules/
        │   │       ├── config/
        │   │       │   ├── mutations.js
        │   │       │   └── sync.js
        │   │       ├── gekkos/
        │   │       │   ├── mutations.js
        │   │       │   └── sync.js
        │   │       ├── imports/
        │   │       │   ├── mutations.js
        │   │       │   └── sync.js
        │   │       ├── messages/
        │   │       │   └── mutations.js
        │   │       └── notifications/
        │   │           ├── mutations.js
        │   │           └── sync.js
        │   └── tools/
        │       ├── ajax.js
        │       ├── api.js
        │       └── marked.js
        └── vue.config.js
Download .txt
Showing preview only (242K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2804 symbols across 39 files)

FILE: core/markets/leech.js
  constant TICKINTERVAL (line 17) | const TICKINTERVAL = 20 * 1000;

FILE: exchange/gekkoBroker.js
  class Broker (line 24) | class Broker {
    method constructor (line 25) | constructor(config) {
    method cantTrade (line 75) | cantTrade() {
    method cantMonitor (line 79) | cantMonitor() {
    method sync (line 83) | sync(callback) {
    method syncPrivateData (line 96) | syncPrivateData(callback) {
    method setTicker (line 107) | setTicker(callback) {
    method isValidOrder (line 127) | isValidOrder(amount, price) {
    method createOrder (line 136) | createOrder(type, side, amount, parameters, handler) {
    method createTrigger (line 170) | createTrigger({type, onTrigger, props}) {

FILE: exchange/orders/limit.js
  class LimitOrder (line 22) | class LimitOrder extends BaseOrder {
    method constructor (line 23) | constructor(api) {
    method create (line 27) | create(side, amount, params) {
    method createOrder (line 38) | createOrder(price, amount) {
    method handleCreate (line 58) | handleCreate(err, id) {
    method checkOrder (line 79) | checkOrder() {
    method handleCheck (line 84) | handleCheck(err, result) {
    method movePrice (line 123) | movePrice(price) {
    method moveAmount (line 168) | moveAmount(amount) {
    method cancel (line 213) | cancel() {

FILE: exchange/orders/order.js
  class BaseOrder (line 11) | class BaseOrder extends EventEmitter {
    method constructor (line 12) | constructor(api) {
    method submit (line 26) | submit({side, amount, price, alreadyFilled}) {
    method setData (line 48) | setData(data) {
    method emitStatus (line 52) | emitStatus() {
    method cancelled (line 56) | cancelled() {
    method rejected (line 63) | rejected(reason) {
    method filled (line 71) | filled(price) {
    method finish (line 79) | finish(filled) {

FILE: exchange/orders/sticky.js
  class StickyOrder (line 23) | class StickyOrder extends BaseOrder {
    method constructor (line 24) | constructor({api, marketConfig, capabilities}) {
    method create (line 44) | create(side, rawAmount, params = {}) {
    method calculatePrice (line 98) | calculatePrice(ticker) {
    method createOrder (line 145) | createOrder() {
    method handleInsufficientFundsError (line 163) | handleInsufficientFundsError(err) {
    method handleCreate (line 204) | handleCreate(err, id) {
    method initiateDefferedAction (line 245) | initiateDefferedAction() {
    method scheduleNextCheck (line 264) | scheduleNextCheck() {
    method checkOrder (line 278) | checkOrder() {
    method handleError (line 400) | handleError(error) {
    method handleCancel (line 418) | handleCancel(filled, data) {
    method move (line 447) | move(price) {
    method calculateFilled (line 481) | calculateFilled() {
    method moveLimit (line 488) | moveLimit(limit) {
    method moveAmount (line 562) | moveAmount(amount) {
    method cancel (line 625) | cancel() {
    method createSummary (line 661) | createSummary(next) {

FILE: exchange/portfolioManager.js
  class Portfolio (line 10) | class Portfolio {
    method constructor (line 11) | constructor(config, api) {
    method getBalance (line 19) | getBalance(fund) {
    method getFund (line 24) | getFund(fund) {
    method convertBalances (line 29) | convertBalances(asset,currency) { // rename?
    method setBalances (line 40) | setBalances(callback) {
    method setFee (line 69) | setFee(callback) {
    method setTicker (line 81) | setTicker(ticker) {

FILE: exchange/trigger.js
  class Trigger (line 14) | class Trigger {
    method constructor (line 15) | constructor({api, type, props, onTrigger}) {
    method scheduleFetch (line 40) | scheduleFetch() {
    method fetch (line 44) | fetch() {
    method processTicker (line 51) | processTicker(err, ticker) {
    method cancel (line 66) | cancel() {
    method propogateTrigger (line 71) | propogateTrigger(payload) {

FILE: exchange/triggers/trailingStop.js
  class TrailingStop (line 10) | class TrailingStop extends EventEmitter {
    method constructor (line 11) | constructor({trail, initialPrice, onTrigger}) {
    method updatePrice (line 22) | updatePrice(price) {
    method updateTrail (line 38) | updateTrail(trail) {
    method trigger (line 49) | trigger() {

FILE: exchange/wrappers/DEBUG_exchange-simulator.js
  constant TREND_DURATION (line 6) | const TREND_DURATION = 1000;

FILE: exchange/wrappers/bittrex.js
  function joinCurrencies (line 7) | function joinCurrencies(currencyA, currencyB){

FILE: exchange/wrappers/gdax.js
  constant BATCH_SIZE (line 8) | const BATCH_SIZE = 100;
  constant QUERY_DELAY (line 9) | const QUERY_DELAY = 350;

FILE: exchange/wrappers/therocktrading.js
  constant QUERY_DELAY (line 7) | const QUERY_DELAY = 350;

FILE: importers/exchanges/bitfinex.js
  constant SCANNING_STRIDE (line 59) | const SCANNING_STRIDE = 24;
  constant ITERATING_STRIDE (line 60) | const ITERATING_STRIDE = 2;

FILE: importers/exchanges/gdax.js
  constant QUERY_DELAY (line 10) | const QUERY_DELAY = 350;
  constant BATCH_SIZE (line 11) | const BATCH_SIZE = 100;
  constant SCAN_ITER_SIZE (line 12) | const SCAN_ITER_SIZE = 50000;
  constant BATCH_ITER_SIZE (line 13) | const BATCH_ITER_SIZE = BATCH_SIZE * 10;

FILE: importers/exchanges/luno.js
  constant REQUEST_INTERVAL (line 14) | const REQUEST_INTERVAL = 5 * 1000;

FILE: importers/exchanges/poloniex.js
  function joinCurrencies (line 17) | function joinCurrencies(currencyA, currencyB){

FILE: plugins/paperTrader/paperTrader.js
  constant ENV (line 4) | const ENV = util.gekkoEnv();

FILE: plugins/performanceAnalyzer/performanceAnalyzer.js
  constant ENV (line 8) | const ENV = util.gekkoEnv();

FILE: plugins/postgresql/util.js
  function useSingleDatabase (line 18) | function useSingleDatabase() {
  function useLowerCaseTableNames (line 27) | function useLowerCaseTableNames() {

FILE: plugins/pushbullet.js
  function getNumStr (line 215) | function getNumStr(num, fixed = 4) {
  function capF (line 279) | function capF(inWord) { //Capitalise first letter of string
  function getPastTense (line 283) | function getPastTense(action) {

FILE: plugins/tradingAdvisor/baseTradingMethod.js
  constant ENV (line 8) | const ENV = util.gekkoEnv();

FILE: strategies/indicators/LRC.js
  function linreg (line 54) | function linreg(values_x, values_y) {

FILE: web/baseUIconfig.js
  constant CONFIG (line 7) | const CONFIG = {

FILE: web/server.js
  constant WEBROOT (line 77) | const WEBROOT = __dirname + '/';

FILE: web/state/logger.js
  constant BASEPATH (line 4) | const BASEPATH = __dirname + '/../../logs/';

FILE: web/vue/dist/UIconfig.js
  constant CONFIG (line 7) | const CONFIG = {

FILE: web/vue/dist/app.5e99ecf7.js
  function e (line 1) | function e(e){for(var n,s,o=e[0],c=e[1],u=e[2],d=0,f=[];d<o.length;d++)s...
  function a (line 1) | function a(){for(var t,e=0;e<i.length;e++){for(var a=i[e],n=!0,o=1;o<a.l...
  function s (line 1) | function s(e){if(n[e])return n[e].exports;var a=n[e]={i:e,l:!1,exports:{...
  function j (line 1) | function j(){if(!d3.event.sourceEvent||"zoom"!==d3.event.sourceEvent.typ...
  function D (line 1) | function D(t){var e=Object(i["a"])(t,2),a=e[0],n=e[1],r=o.a.sortedIndex(...
  function O (line 1) | function O(){if(!d3.event.sourceEvent||"brush"!==d3.event.sourceEvent.ty...
  function e (line 1) | function e(e){return t.apply(this,arguments)}
  function e (line 1) | function e(e){return t.apply(this,arguments)}

FILE: web/vue/dist/chunk-vendors.b9a11975.js
  function i (line 1) | function i(t){if(t)return o(t)}
  function o (line 1) | function o(t){for(var e in i.prototype)t[e]=i.prototype[e];return t}
  function c (line 1) | function c(){}
  function p (line 1) | function p(t){if(!a(t))return t;var e=[];for(var n in t)h(e,n,t[n]);retu...
  function h (line 1) | function h(t,e,n){if(null!=n)if(Array.isArray(n))n.forEach(function(n){h...
  function d (line 1) | function d(t){for(var e,n,r={},i=t.split("&"),o=0,a=i.length;o<a;++o)e=i...
  function v (line 1) | function v(t){for(var e,n,r,i,o=t.split(/\r?\n/),a={},u=0,s=o.length;u<s...
  function y (line 1) | function y(t){return/[\/+]json($|[^-\w])/.test(t)}
  function g (line 1) | function g(t){this.req=t,this.xhr=this.req.xhr,this.text="HEAD"!=this.re...
  function _ (line 1) | function _(t,e){var n=this;this._query=this._query||[],this.method=t,thi...
  function m (line 1) | function m(t,e,n){var r=l("DELETE",t);return"function"==typeof e&&(n=e,e...
  function r (line 1) | function r(t){return null!==t&&"object"===typeof t}
  function r (line 1) | function r(t){this.tokens=[],this.tokens.links={},this.options=t||_.defa...
  function o (line 1) | function o(t,e){if(this.options=e||_.defaults,this.links=t,this.rules=i....
  function a (line 1) | function a(t){this.options=t||_.defaults}
  function u (line 1) | function u(){}
  function s (line 1) | function s(t){this.tokens=[],this.token=null,this.options=t||_.defaults,...
  function c (line 1) | function c(t,e){return t.replace(e?/&/g:/&(?!#?\w+;)/g,"&amp;").replace(...
  function l (line 1) | function l(t){return t.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?...
  function f (line 1) | function f(t,e){return t=t.source||t,e=e||"",{replace:function(e,n){retu...
  function p (line 1) | function p(t,e){return h[" "+t]||(/^[^:]+:\/*[^/]*$/.test(t)?h[" "+t]=t+...
  function v (line 1) | function v(){}
  function y (line 1) | function y(t){for(var e,n,r=1;r<arguments.length;r++)for(n in e=argument...
  function g (line 1) | function g(t,e){var n=t.replace(/([^\\])\|/g,"$1 |").split(/ +\| */),r=0...
  function _ (line 1) | function _(t,e,n){if("undefined"===typeof t||null===t)throw new Error("m...
  function r (line 1) | function r(t,e,n,r,i,o,a,u){var s,c="function"===typeof t?t.options:t;if...
  function r (line 7) | function r(t){return void 0===t||null===t}
  function i (line 7) | function i(t){return void 0!==t&&null!==t}
  function o (line 7) | function o(t){return!0===t}
  function a (line 7) | function a(t){return!1===t}
  function u (line 7) | function u(t){return"string"===typeof t||"number"===typeof t||"symbol"==...
  function s (line 7) | function s(t){return null!==t&&"object"===typeof t}
  function l (line 7) | function l(t){return"[object Object]"===c.call(t)}
  function f (line 7) | function f(t){return"[object RegExp]"===c.call(t)}
  function p (line 7) | function p(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e...
  function h (line 7) | function h(t){return null==t?"":"object"===typeof t?JSON.stringify(t,nul...
  function d (line 7) | function d(t){var e=parseFloat(t);return isNaN(e)?t:e}
  function v (line 7) | function v(t,e){for(var n=Object.create(null),r=t.split(","),i=0;i<r.len...
  function g (line 7) | function g(t,e){if(t.length){var n=t.indexOf(e);if(n>-1)return t.splice(...
  function m (line 7) | function m(t,e){return _.call(t,e)}
  function b (line 7) | function b(t){var e=Object.create(null);return function(n){var r=e[n];re...
  function C (line 7) | function C(t,e){function n(n){var r=arguments.length;return r?r>1?t.appl...
  function E (line 7) | function E(t,e){return t.bind(e)}
  function S (line 7) | function S(t,e){e=e||0;var n=t.length-e,r=new Array(n);while(n--)r[n]=t[...
  function $ (line 7) | function $(t,e){for(var n in e)t[n]=e[n];return t}
  function T (line 7) | function T(t){for(var e={},n=0;n<t.length;n++)t[n]&&$(e,t[n]);return e}
  function R (line 7) | function R(t,e,n){}
  function P (line 7) | function P(t,e){if(t===e)return!0;var n=s(t),r=s(e);if(!n||!r)return!n&&...
  function M (line 7) | function M(t,e){for(var n=0;n<t.length;n++)if(P(t[n],e))return n;return-1}
  function D (line 7) | function D(t){var e=!1;return function(){e||(e=!0,t.apply(this,arguments...
  function F (line 7) | function F(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}
  function H (line 7) | function H(t,e,n,r){Object.defineProperty(t,e,{value:n,enumerable:!!r,wr...
  function B (line 7) | function B(t){if(!W.test(t)){var e=t.split(".");return function(t){for(v...
  function ut (line 7) | function ut(t){return"function"===typeof t&&/native code/.test(t.toStrin...
  function t (line 7) | function t(){this.set=Object.create(null)}
  function dt (line 7) | function dt(t){pt.target&&ht.push(pt.target),pt.target=t}
  function vt (line 7) | function vt(){pt.target=ht.pop()}
  function mt (line 7) | function mt(t){return new yt(void 0,void 0,void 0,String(t))}
  function bt (line 7) | function bt(t){var e=new yt(t.tag,t.data,t.children,t.text,t.elm,t.conte...
  function Ct (line 7) | function Ct(t){Ot=t}
  function jt (line 7) | function jt(t,e,n){t.__proto__=e}
  function St (line 7) | function St(t,e,n){for(var r=0,i=n.length;r<i;r++){var o=n[r];H(t,o,e[o])}}
  function $t (line 7) | function $t(t,e){var n;if(s(t)&&!(t instanceof yt))return m(t,"__ob__")&...
  function Tt (line 7) | function Tt(t,e,n,r,i){var o=new pt,a=Object.getOwnPropertyDescriptor(t,...
  function Rt (line 7) | function Rt(t,e,n){if(Array.isArray(t)&&p(e))return t.length=Math.max(t....
  function Lt (line 7) | function Lt(t,e){if(Array.isArray(t)&&p(e))t.splice(e,1);else{var n=t.__...
  function It (line 7) | function It(t){for(var e=void 0,n=0,r=t.length;n<r;n++)e=t[n],e&&e.__ob_...
  function Mt (line 7) | function Mt(t,e){if(!e)return t;for(var n,r,i,o=Object.keys(e),a=0;a<o.l...
  function Dt (line 7) | function Dt(t,e,n){return n?function(){var r="function"===typeof e?e.cal...
  function Ut (line 7) | function Ut(t,e){return e?t?t.concat(e):Array.isArray(e)?e:[e]:t}
  function zt (line 7) | function zt(t,e,n,r){var i=Object.create(t||null);return e?$(i,e):i}
  function Nt (line 7) | function Nt(t,e){var n=t.props;if(n){var r,i,o,a={};if(Array.isArray(n))...
  function Ft (line 7) | function Ft(t,e){var n=t.inject;if(n){var r=t.inject={};if(Array.isArray...
  function Ht (line 7) | function Ht(t){var e=t.directives;if(e)for(var n in e){var r=e[n];"funct...
  function Wt (line 7) | function Wt(t,e,n){"function"===typeof e&&(e=e.options),Nt(e,n),Ft(e,n),...
  function Bt (line 7) | function Bt(t,e,n,r){if("string"===typeof n){var i=t[e];if(m(i,n))return...
  function Kt (line 7) | function Kt(t,e,n,r){var i=e[t],o=!m(n,t),a=n[t],u=Gt(Boolean,i.type);if...
  function Vt (line 7) | function Vt(t,e,n){if(m(e,"default")){var r=e.default;return t&&t.$optio...
  function Zt (line 7) | function Zt(t){var e=t&&t.toString().match(/^\s*function (\w+)/);return ...
  function Xt (line 7) | function Xt(t,e){return Zt(t)===Zt(e)}
  function Gt (line 7) | function Gt(t,e){if(!Array.isArray(e))return Xt(e,t)?0:-1;for(var n=0,r=...
  function Jt (line 7) | function Jt(t,e,n){if(e){var r=e;while(r=r.$parent){var i=r.$options.err...
  function Yt (line 7) | function Yt(t,e,n){if(N.errorHandler)try{return N.errorHandler.call(null...
  function Qt (line 7) | function Qt(t,e,n){if(!Z&&!X||"undefined"===typeof console)throw t;conso...
  function ie (line 7) | function ie(){re=!1;var t=ne.slice(0);ne.length=0;for(var e=0;e<t.length...
  function ce (line 7) | function ce(t){return t._withTask||(t._withTask=function(){oe=!0;var e=t...
  function le (line 7) | function le(t,e){var n;if(ne.push(function(){if(t)try{t.call(e)}catch(t)...
  function pe (line 7) | function pe(t){he(t,fe),fe.clear()}
  function he (line 7) | function he(t,e){var n,r,i=Array.isArray(t);if(!(!i&&!s(t)||Object.isFro...
  function ye (line 7) | function ye(t){function e(){var t=arguments,n=e.fns;if(!Array.isArray(n)...
  function ge (line 7) | function ge(t,e,n,i,o){var a,u,s,c;for(a in t)u=t[a],s=e[a],c=ve(a),r(u)...
  function _e (line 7) | function _e(t,e,n){var a;t instanceof yt&&(t=t.data.hook||(t.data.hook={...
  function me (line 7) | function me(t,e,n){var o=e.options.props;if(!r(o)){var a={},u=t.attrs,s=...
  function be (line 7) | function be(t,e,n,r,o){if(i(e)){if(m(e,n))return t[n]=e[n],o||delete e[n...
  function we (line 7) | function we(t){for(var e=0;e<t.length;e++)if(Array.isArray(t[e]))return ...
  function xe (line 7) | function xe(t){return u(t)?[mt(t)]:Array.isArray(t)?Ae(t):void 0}
  function ke (line 7) | function ke(t){return i(t)&&i(t.text)&&a(t.isComment)}
  function Ae (line 7) | function Ae(t,e){var n,a,s,c,l=[];for(n=0;n<t.length;n++)a=t[n],r(a)||"b...
  function Oe (line 7) | function Oe(t,e){return(t.__esModule||ct&&"Module"===t[Symbol.toStringTa...
  function Ce (line 7) | function Ce(t,e,n,r,i){var o=_t();return o.asyncFactory=t,o.asyncMeta={d...
  function Ee (line 7) | function Ee(t,e,n){if(o(t.error)&&i(t.errorComp))return t.errorComp;if(i...
  function je (line 7) | function je(t){return t.isComment&&t.asyncFactory}
  function Se (line 7) | function Se(t){if(Array.isArray(t))for(var e=0;e<t.length;e++){var n=t[e...
  function $e (line 7) | function $e(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t....
  function Te (line 7) | function Te(t,e,n){n?de.$once(t,e):de.$on(t,e)}
  function Re (line 7) | function Re(t,e){de.$off(t,e)}
  function Le (line 7) | function Le(t,e,n){de=t,ge(e,n||{},Te,Re,t),de=void 0}
  function Ie (line 7) | function Ie(t){var e=/^hook:/;t.prototype.$on=function(t,n){var r=this,i...
  function Pe (line 7) | function Pe(t,e){var n={};if(!t)return n;for(var r=0,i=t.length;r<i;r++)...
  function Me (line 7) | function Me(t){return t.isComment&&!t.asyncFactory||" "===t.text}
  function De (line 7) | function De(t,e){e=e||{};for(var n=0;n<t.length;n++)Array.isArray(t[n])?...
  function ze (line 7) | function ze(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){while(n.$o...
  function qe (line 7) | function qe(t){t.prototype._update=function(t,e){var n=this;n._isMounted...
  function Ne (line 7) | function Ne(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.r...
  function Fe (line 7) | function Fe(t,e,r,i,o){var a=!!(o||t.$options._renderChildren||i.data.sc...
  function He (line 7) | function He(t){while(t&&(t=t.$parent))if(t._inactive)return!0;return!1}
  function We (line 7) | function We(t,e){if(e){if(t._directInactive=!1,He(t))return}else if(t._d...
  function Be (line 7) | function Be(t,e){if((!e||(t._directInactive=!0,!He(t)))&&!t._inactive){t...
  function Ke (line 7) | function Ke(t,e){dt();var n=t.$options[e];if(n)for(var r=0,i=n.length;r<...
  function Qe (line 7) | function Qe(){Ye=Ve.length=Ze.length=0,Xe={},Ge=Je=!1}
  function tn (line 7) | function tn(){var t,e;for(Je=!0,Ve.sort(function(t,e){return t.id-e.id})...
  function en (line 7) | function en(t){var e=t.length;while(e--){var n=t[e],r=n.vm;r._watcher===...
  function nn (line 7) | function nn(t){t._inactive=!1,Ze.push(t)}
  function rn (line 7) | function rn(t){for(var e=0;e<t.length;e++)t[e]._inactive=!0,We(t[e],!0)}
  function on (line 7) | function on(t){var e=t.id;if(null==Xe[e]){if(Xe[e]=!0,Je){var n=Ve.lengt...
  function cn (line 7) | function cn(t,e,n){sn.get=function(){return this[e][n]},sn.set=function(...
  function ln (line 7) | function ln(t){t._watchers=[];var e=t.$options;e.props&&fn(t,e.props),e....
  function fn (line 7) | function fn(t,e){var n=t.$options.propsData||{},r=t._props={},i=t.$optio...
  function pn (line 7) | function pn(t){var e=t.$options.data;e=t._data="function"===typeof e?hn(...
  function hn (line 7) | function hn(t,e){dt();try{return t.call(e,e)}catch(t){return Jt(t,e,"dat...
  function vn (line 7) | function vn(t,e){var n=t._computedWatchers=Object.create(null),r=ot();fo...
  function yn (line 7) | function yn(t,e,n){var r=!ot();"function"===typeof n?(sn.get=r?gn(e):n,s...
  function gn (line 7) | function gn(t){return function(){var e=this._computedWatchers&&this._com...
  function _n (line 7) | function _n(t,e){t.$options.props;for(var n in e)t[n]=null==e[n]?R:j(e[n...
  function mn (line 7) | function mn(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var ...
  function bn (line 7) | function bn(t,e,n,r){return l(n)&&(r=n,n=n.handler),"string"===typeof n&...
  function wn (line 7) | function wn(t){var e={get:function(){return this._data}},n={get:function...
  function xn (line 7) | function xn(t){var e=t.$options.provide;e&&(t._provided="function"===typ...
  function kn (line 7) | function kn(t){var e=An(t.$options.inject,t);e&&(Ct(!1),Object.keys(e).f...
  function An (line 7) | function An(t,e){if(t){for(var n=Object.create(null),r=ct?Reflect.ownKey...
  function On (line 7) | function On(t,e){var n,r,o,a,u;if(Array.isArray(t)||"string"===typeof t)...
  function Cn (line 7) | function Cn(t,e,n,r){var i,o=this.$scopedSlots[t];if(o)n=n||{},r&&(n=$($...
  function En (line 7) | function En(t){return Bt(this.$options,"filters",t,!0)||I}
  function jn (line 7) | function jn(t,e){return Array.isArray(t)?-1===t.indexOf(e):t!==e}
  function Sn (line 7) | function Sn(t,e,n,r,i){var o=N.keyCodes[e]||n;return i&&r&&!N.keyCodes[e...
  function $n (line 7) | function $n(t,e,n,r,i){if(n)if(s(n)){var o;Array.isArray(n)&&(n=T(n));va...
  function Tn (line 7) | function Tn(t,e){var n=this._staticTrees||(this._staticTrees=[]),r=n[t];...
  function Rn (line 7) | function Rn(t,e,n){return Ln(t,"__once__"+e+(n?"_"+n:""),!0),t}
  function Ln (line 7) | function Ln(t,e,n){if(Array.isArray(t))for(var r=0;r<t.length;r++)t[r]&&...
  function In (line 7) | function In(t,e,n){t.isStatic=!0,t.key=e,t.isOnce=n}
  function Pn (line 7) | function Pn(t,e){if(e)if(l(e)){var n=t.on=t.on?$({},t.on):{};for(var r i...
  function Mn (line 7) | function Mn(t){t._o=Rn,t._n=d,t._s=h,t._l=On,t._t=Cn,t._q=P,t._i=M,t._m=...
  function Dn (line 7) | function Dn(t,e,r,i,a){var u,s=a.options;m(i,"_uid")?(u=Object.create(i)...
  function Un (line 7) | function Un(t,e,r,o,a){var u=t.options,s={},c=u.props;if(i(c))for(var l ...
  function zn (line 7) | function zn(t,e,n,r){var i=bt(t);return i.fnContext=n,i.fnOptions=r,e.sl...
  function qn (line 7) | function qn(t,e){for(var n in e)t[x(n)]=e[n]}
  function Hn (line 7) | function Hn(t,e,n,a,u){if(!r(t)){var c=n.$options._base;if(s(t)&&(t=c.ex...
  function Wn (line 7) | function Wn(t,e,n,r){var o={_isComponent:!0,parent:e,_parentVnode:t,_par...
  function Bn (line 7) | function Bn(t){for(var e=t.hook||(t.hook={}),n=0;n<Fn.length;n++){var r=...
  function Kn (line 7) | function Kn(t,e){var n=t.model&&t.model.prop||"value",r=t.model&&t.model...
  function Xn (line 7) | function Xn(t,e,n,r,i,a){return(Array.isArray(n)||u(n))&&(i=r,r=n,n=void...
  function Gn (line 7) | function Gn(t,e,n,r,o){if(i(n)&&i(n.__ob__))return _t();if(i(n)&&i(n.is)...
  function Jn (line 7) | function Jn(t,e,n){if(t.ns=e,"foreignObject"===t.tag&&(e=void 0,n=!0),i(...
  function Yn (line 7) | function Yn(t){s(t.style)&&pe(t.style),s(t.class)&&pe(t.class)}
  function Qn (line 7) | function Qn(t){t._vnode=null,t._staticTrees=null;var e=t.$options,r=t.$v...
  function tr (line 7) | function tr(t){Mn(t.prototype),t.prototype.$nextTick=function(t){return ...
  function nr (line 7) | function nr(t){t.prototype._init=function(t){var e=this;e._uid=er++,e._i...
  function rr (line 7) | function rr(t,e){var n=t.$options=Object.create(t.constructor.options),r...
  function ir (line 7) | function ir(t){var e=t.options;if(t.super){var n=ir(t.super),r=t.superOp...
  function or (line 7) | function or(t){var e,n=t.options,r=t.extendOptions,i=t.sealedOptions;for...
  function ar (line 7) | function ar(t,e,n){if(Array.isArray(t)){var r=[];n=Array.isArray(n)?n:[n...
  function ur (line 7) | function ur(t){this._init(t)}
  function sr (line 7) | function sr(t){t.use=function(t){var e=this._installedPlugins||(this._in...
  function cr (line 7) | function cr(t){t.mixin=function(t){return this.options=Wt(this.options,t...
  function lr (line 7) | function lr(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r...
  function fr (line 7) | function fr(t){var e=t.options.props;for(var n in e)cn(t.prototype,"_pro...
  function pr (line 7) | function pr(t){var e=t.options.computed;for(var n in e)yn(t.prototype,n,...
  function hr (line 7) | function hr(t){z.forEach(function(e){t[e]=function(t,n){return n?("compo...
  function dr (line 7) | function dr(t){return t&&(t.Ctor.options.name||t.tag)}
  function vr (line 7) | function vr(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"===type...
  function yr (line 7) | function yr(t,e){var n=t.cache,r=t.keys,i=t._vnode;for(var o in n){var a...
  function gr (line 7) | function gr(t,e,n,r){var i=t[e];!i||r&&i.tag===r.tag||i.componentInstanc...
  function wr (line 7) | function wr(t){var e={get:function(){return N}};Object.defineProperty(t,...
  function Tr (line 7) | function Tr(t){var e=t.data,n=t,r=t;while(i(r.componentInstance))r=r.com...
  function Rr (line 7) | function Rr(t,e){return{staticClass:Ir(t.staticClass,e.staticClass),clas...
  function Lr (line 7) | function Lr(t,e){return i(t)||i(e)?Ir(t,Pr(e)):""}
  function Ir (line 7) | function Ir(t,e){return t?e?t+" "+e:t:e||""}
  function Pr (line 7) | function Pr(t){return Array.isArray(t)?Mr(t):s(t)?Dr(t):"string"===typeo...
  function Mr (line 7) | function Mr(t){for(var e,n="",r=0,o=t.length;r<o;r++)i(e=Pr(t[r]))&&""!=...
  function Dr (line 7) | function Dr(t){var e="";for(var n in t)t[n]&&(e&&(e+=" "),e+=n);return e}
  function Fr (line 7) | function Fr(t){return qr(t)?"svg":"math"===t?"math":void 0}
  function Wr (line 7) | function Wr(t){if(!Z)return!0;if(Nr(t))return!1;if(t=t.toLowerCase(),nul...
  function Kr (line 7) | function Kr(t){if("string"===typeof t){var e=document.querySelector(t);r...
  function Vr (line 7) | function Vr(t,e){var n=document.createElement(t);return"select"!==t?n:(e...
  function Zr (line 7) | function Zr(t,e){return document.createElementNS(Ur[t],e)}
  function Xr (line 7) | function Xr(t){return document.createTextNode(t)}
  function Gr (line 7) | function Gr(t){return document.createComment(t)}
  function Jr (line 7) | function Jr(t,e,n){t.insertBefore(e,n)}
  function Yr (line 7) | function Yr(t,e){t.removeChild(e)}
  function Qr (line 7) | function Qr(t,e){t.appendChild(e)}
  function ti (line 7) | function ti(t){return t.parentNode}
  function ei (line 7) | function ei(t){return t.nextSibling}
  function ni (line 7) | function ni(t){return t.tagName}
  function ri (line 7) | function ri(t,e){t.textContent=e}
  function ii (line 7) | function ii(t,e){t.setAttribute(e,"")}
  function ui (line 7) | function ui(t,e){var n=t.data.ref;if(i(n)){var r=t.context,o=t.component...
  function li (line 7) | function li(t,e){return t.key===e.key&&(t.tag===e.tag&&t.isComment===e.i...
  function fi (line 7) | function fi(t,e){if("input"!==t.tag)return!0;var n,r=i(n=t.data)&&i(n=n....
  function pi (line 7) | function pi(t,e,n){var r,o,a={};for(r=e;r<=n;++r)o=t[r].key,i(o)&&(a[o]=...
  function hi (line 7) | function hi(t){var e,n,a={},s=t.modules,c=t.nodeOps;for(e=0;e<ci.length;...
  function vi (line 7) | function vi(t,e){(t.data.directives||e.data.directives)&&yi(t,e)}
  function yi (line 7) | function yi(t,e){var n,r,i,o=t===si,a=e===si,u=_i(t.data.directives,t.co...
  function _i (line 7) | function _i(t,e){var n,r,i=Object.create(null);if(!t)return i;for(n=0;n<...
  function mi (line 7) | function mi(t){return t.rawName||t.name+"."+Object.keys(t.modifiers||{})...
  function bi (line 7) | function bi(t,e,n,r,i){var o=t.def&&t.def[e];if(o)try{o(n.elm,t,n,r,i)}c...
  function xi (line 7) | function xi(t,e){var n=e.componentOptions;if((!i(n)||!1!==n.Ctor.options...
  function ki (line 7) | function ki(t,e,n){t.tagName.indexOf("-")>-1?Ai(t,e,n):Cr(e)?$r(n)?t.rem...
  function Ai (line 7) | function Ai(t,e,n){if($r(n))t.removeAttribute(e);else{if(Y&&!Q&&"TEXTARE...
  function Ci (line 7) | function Ci(t,e){var n=e.elm,o=e.data,a=t.data;if(!(r(o.staticClass)&&r(...
  function Ti (line 7) | function Ti(t){if(i(t[Si])){var e=Y?"change":"input";t[e]=[].concat(t[Si...
  function Ri (line 7) | function Ri(t,e,n){var r=Ei;return function i(){var o=t.apply(null,argum...
  function Li (line 7) | function Li(t,e,n,r,i){e=ce(e),n&&(e=Ri(e,t,r)),Ei.addEventListener(t,e,...
  function Ii (line 7) | function Ii(t,e,n,r){(r||Ei).removeEventListener(t,e._withTask||e,n)}
  function Pi (line 7) | function Pi(t,e){if(!r(t.data.on)||!r(e.data.on)){var n=e.data.on||{},i=...
  function Di (line 7) | function Di(t,e){if(!r(t.data.domProps)||!r(e.data.domProps)){var n,o,a=...
  function Ui (line 7) | function Ui(t,e){return!t.composing&&("OPTION"===t.tagName||zi(t,e)||qi(...
  function zi (line 7) | function zi(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}ret...
  function qi (line 7) | function qi(t,e){var n=t.value,r=t._vModifiers;if(i(r)){if(r.lazy)return...
  function Hi (line 7) | function Hi(t){var e=Wi(t.style);return t.staticStyle?$(t.staticStyle,e):e}
  function Wi (line 7) | function Wi(t){return Array.isArray(t)?T(t):"string"===typeof t?Fi(t):t}
  function Bi (line 7) | function Bi(t,e){var n,r={};if(e){var i=t;while(i.componentInstance)i=i....
  function Yi (line 7) | function Yi(t,e){var n=e.data,o=t.data;if(!(r(n.staticStyle)&&r(n.style)...
  function to (line 7) | function to(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
  function eo (line 7) | function eo(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.s...
  function no (line 7) | function no(t){if(t){if("object"===typeof t){var e={};return!1!==t.css&&...
  function po (line 7) | function po(t){fo(function(){fo(t)})}
  function ho (line 7) | function ho(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n...
  function vo (line 7) | function vo(t,e){t._transitionClasses&&g(t._transitionClasses,e),eo(t,e)}
  function yo (line 7) | function yo(t,e,n){var r=_o(t,e),i=r.type,o=r.timeout,a=r.propCount;if(!...
  function _o (line 7) | function _o(t,e){var n,r=window.getComputedStyle(t),i=r[uo+"Delay"].spli...
  function mo (line 7) | function mo(t,e){while(t.length<e.length)t=t.concat(t);return Math.max.a...
  function bo (line 7) | function bo(t){return 1e3*Number(t.slice(0,-1))}
  function wo (line 7) | function wo(t,e){var n=t.elm;i(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._...
  function xo (line 7) | function xo(t,e){var n=t.elm;i(n._enterCb)&&(n._enterCb.cancelled=!0,n._...
  function ko (line 7) | function ko(t){return"number"===typeof t&&!isNaN(t)}
  function Ao (line 7) | function Ao(t){if(r(t))return!1;var e=t.fns;return i(e)?Ao(Array.isArray...
  function Oo (line 7) | function Oo(t,e){!0!==e.data.show&&wo(e)}
  function To (line 7) | function To(t,e,n){Ro(t,e,n),(Y||tt)&&setTimeout(function(){Ro(t,e,n)},0)}
  function Ro (line 7) | function Ro(t,e,n){var r=e.value,i=t.multiple;if(!i||Array.isArray(r)){f...
  function Lo (line 7) | function Lo(t,e){return e.every(function(e){return!P(e,t)})}
  function Io (line 7) | function Io(t){return"_value"in t?t._value:t.value}
  function Po (line 7) | function Po(t){t.target.composing=!0}
  function Mo (line 7) | function Mo(t){t.target.composing&&(t.target.composing=!1,Do(t.target,"i...
  function Do (line 7) | function Do(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,...
  function Uo (line 7) | function Uo(t){return!t.componentInstance||t.data&&t.data.transition?t:U...
  function Fo (line 7) | function Fo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abst...
  function Ho (line 7) | function Ho(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];...
  function Wo (line 7) | function Wo(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{...
  function Bo (line 7) | function Bo(t){while(t=t.parent)if(t.data.transition)return!0}
  function Ko (line 7) | function Ko(t,e){return e.key===t.key&&e.tag===t.tag}
  function Go (line 7) | function Go(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._ent...
  function Jo (line 7) | function Jo(t){t.data.newPos=t.elm.getBoundingClientRect()}
  function Yo (line 7) | function Yo(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,i=e.top-...
  function r (line 12) | function r(){var t=this.$options;t.store?this.$store="function"===typeof...
  function o (line 12) | function o(t){i&&(t._devtoolHook=i,i.emit("vuex:init",t),i.on("vuex:trav...
  function a (line 12) | function a(t,e){Object.keys(t).forEach(function(n){return e(t[n],n)})}
  function u (line 12) | function u(t){return null!==t&&"object"===typeof t}
  function s (line 12) | function s(t){return t&&"function"===typeof t.then}
  function p (line 12) | function p(t,e,n){if(e.update(n),n.modules)for(var r in n.modules){if(!e...
  function y (line 12) | function y(t,e){return e.indexOf(t)<0&&e.push(t),function(){var n=e.inde...
  function g (line 12) | function g(t,e){t._actions=Object.create(null),t._mutations=Object.creat...
  function _ (line 12) | function _(t,e,n){var r=t._vm;t.getters={};var i=t._wrappedGetters,o={};...
  function m (line 12) | function m(t,e,n,r,i){var o=!n.length,a=t._modules.getNamespace(n);if(r....
  function b (line 12) | function b(t,e,n){var r=""===e,i={dispatch:r?t.dispatch:function(n,r,i){...
  function w (line 12) | function w(t,e){var n={},r=e.length;return Object.keys(t.getters).forEac...
  function x (line 12) | function x(t,e,n,r){var i=t._mutations[e]||(t._mutations[e]=[]);i.push(f...
  function k (line 12) | function k(t,e,n,r){var i=t._actions[e]||(t._actions[e]=[]);i.push(funct...
  function A (line 12) | function A(t,e,n,r){t._wrappedGetters[e]||(t._wrappedGetters[e]=function...
  function O (line 12) | function O(t){t._vm.$watch(function(){return this._data.$$state},functio...
  function C (line 12) | function C(t,e){return e.length?e.reduce(function(t,e){return t[e]},t):t}
  function E (line 12) | function E(t,e,n){return u(t)&&t.type&&(n=e,e=t,t=t.type),{type:t,payloa...
  function j (line 12) | function j(t){h&&t===h||(h=t,r(h))}
  function I (line 12) | function I(t){return Array.isArray(t)?t.map(function(t){return{key:t,val...
  function P (line 12) | function P(t){return function(e,n){return"string"!==typeof e?(n=e,e=""):...
  function M (line 12) | function M(t,e,n){var r=t._modulesNamespaceMap[n];return r}
  function mn (line 20) | function mn(t,e,n){switch(n.length){case 0:return t.call(e);case 1:retur...
  function bn (line 20) | function bn(t,e,n,r){var i=-1,o=null==t?0:t.length;while(++i<o){var a=t[...
  function wn (line 20) | function wn(t,e){var n=-1,r=null==t?0:t.length;while(++n<r)if(!1===e(t[n...
  function xn (line 20) | function xn(t,e){var n=null==t?0:t.length;while(n--)if(!1===e(t[n],n,t))...
  function kn (line 20) | function kn(t,e){var n=-1,r=null==t?0:t.length;while(++n<r)if(!e(t[n],n,...
  function An (line 20) | function An(t,e){var n=-1,r=null==t?0:t.length,i=0,o=[];while(++n<r){var...
  function On (line 20) | function On(t,e){var n=null==t?0:t.length;return!!n&&Dn(t,e,0)>-1}
  function Cn (line 20) | function Cn(t,e,n){var r=-1,i=null==t?0:t.length;while(++r<i)if(n(e,t[r]...
  function En (line 20) | function En(t,e){var n=-1,r=null==t?0:t.length,i=Array(r);while(++n<r)i[...
  function jn (line 20) | function jn(t,e){var n=-1,r=e.length,i=t.length;while(++n<r)t[i+n]=e[n];...
  function Sn (line 20) | function Sn(t,e,n,r){var i=-1,o=null==t?0:t.length;r&&o&&(n=t[++i]);whil...
  function $n (line 20) | function $n(t,e,n,r){var i=null==t?0:t.length;r&&i&&(n=t[--i]);while(i--...
  function Tn (line 20) | function Tn(t,e){var n=-1,r=null==t?0:t.length;while(++n<r)if(e(t[n],n,t...
  function Ln (line 20) | function Ln(t){return t.split("")}
  function In (line 20) | function In(t){return t.match(Ht)||[]}
  function Pn (line 20) | function Pn(t,e,n){var r;return n(t,function(t,n,i){if(e(t,n,i))return r...
  function Mn (line 20) | function Mn(t,e,n,r){var i=t.length,o=n+(r?1:-1);while(r?o--:++o<i)if(e(...
  function Dn (line 20) | function Dn(t,e,n){return e===e?hr(t,e,n):Mn(t,zn,n)}
  function Un (line 20) | function Un(t,e,n,r){var i=n-1,o=t.length;while(++i<o)if(r(t[i],e))retur...
  function zn (line 20) | function zn(t){return t!==t}
  function qn (line 20) | function qn(t,e){var n=null==t?0:t.length;return n?Bn(t,e)/n:U}
  function Nn (line 20) | function Nn(t){return function(e){return null==e?o:e[t]}}
  function Fn (line 20) | function Fn(t){return function(e){return null==t?o:t[e]}}
  function Hn (line 20) | function Hn(t,e,n,r,i){return i(t,function(t,i,o){n=r?(r=!1,t):e(n,t,i,o...
  function Wn (line 20) | function Wn(t,e){var n=t.length;t.sort(e);while(n--)t[n]=t[n].value;retu...
  function Bn (line 20) | function Bn(t,e){var n,r=-1,i=t.length;while(++r<i){var a=e(t[r]);a!==o&...
  function Kn (line 20) | function Kn(t,e){var n=-1,r=Array(t);while(++n<t)r[n]=e(n);return r}
  function Vn (line 20) | function Vn(t,e){return En(e,function(e){return[e,t[e]]})}
  function Zn (line 20) | function Zn(t){return function(e){return t(e)}}
  function Xn (line 20) | function Xn(t,e){return En(e,function(e){return t[e]})}
  function Gn (line 20) | function Gn(t,e){return t.has(e)}
  function Jn (line 20) | function Jn(t,e){var n=-1,r=t.length;while(++n<r&&Dn(e,t[n],0)>-1);retur...
  function Yn (line 20) | function Yn(t,e){var n=t.length;while(n--&&Dn(e,t[n],0)>-1);return n}
  function Qn (line 20) | function Qn(t,e){var n=t.length,r=0;while(n--)t[n]===e&&++r;return r}
  function nr (line 20) | function nr(t){return"\\"+en[t]}
  function rr (line 20) | function rr(t,e){return null==t?o:t[e]}
  function ir (line 20) | function ir(t){return Ke.test(t)}
  function or (line 20) | function or(t){return Ve.test(t)}
  function ar (line 20) | function ar(t){var e,n=[];while(!(e=t.next()).done)n.push(e.value);retur...
  function ur (line 20) | function ur(t){var e=-1,n=Array(t.size);return t.forEach(function(t,r){n...
  function sr (line 20) | function sr(t,e){return function(n){return t(e(n))}}
  function cr (line 20) | function cr(t,e){var n=-1,r=t.length,i=0,o=[];while(++n<r){var a=t[n];a!...
  function lr (line 20) | function lr(t,e){return"__proto__"==e?o:t[e]}
  function fr (line 20) | function fr(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[+...
  function pr (line 20) | function pr(t){var e=-1,n=Array(t.size);return t.forEach(function(t){n[+...
  function hr (line 20) | function hr(t,e,n){var r=n-1,i=t.length;while(++r<i)if(t[r]===e)return r...
  function dr (line 20) | function dr(t,e,n){var r=n+1;while(r--)if(t[r]===e)return r;return r}
  function vr (line 20) | function vr(t){return ir(t)?_r(t):Rn(t)}
  function yr (line 20) | function yr(t){return ir(t)?mr(t):Ln(t)}
  function _r (line 20) | function _r(t){var e=We.lastIndex=0;while(We.test(t))++e;return e}
  function mr (line 20) | function mr(t){return t.match(We)||[]}
  function br (line 20) | function br(t){return t.match(Be)||[]}
  function wr (line 20) | function wr(t){if(kl(t)&&!al(t)&&!(t instanceof Cr)){if(t instanceof Or)...
  function t (line 20) | function t(){}
  function Ar (line 20) | function Ar(){}
  function Or (line 20) | function Or(t,e){this.__wrapped__=t,this.__actions__=[],this.__chain__=!...
  function Cr (line 20) | function Cr(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,thi...
  function Er (line 20) | function Er(){var t=new Cr(this.__wrapped__);return t.__actions__=ra(thi...
  function jr (line 20) | function jr(){if(this.__filtered__){var t=new Cr(this);t.__dir__=-1,t.__...
  function Sr (line 20) | function Sr(){var t=this.__wrapped__.value(),e=this.__dir__,n=al(t),r=e<...
  function $r (line 20) | function $r(t){var e=-1,n=null==t?0:t.length;this.clear();while(++e<n){v...
  function Tr (line 20) | function Tr(){this.__data__=an?an(null):{},this.size=0}
  function Rr (line 20) | function Rr(t){var e=this.has(t)&&delete this.__data__[t];return this.si...
  function Lr (line 20) | function Lr(t){var e=this.__data__;if(an){var n=e[t];return n===l?o:n}re...
  function Ir (line 20) | function Ir(t){var e=this.__data__;return an?e[t]!==o:fe.call(e,t)}
  function Pr (line 20) | function Pr(t,e){var n=this.__data__;return this.size+=this.has(t)?0:1,n...
  function Mr (line 20) | function Mr(t){var e=-1,n=null==t?0:t.length;this.clear();while(++e<n){v...
  function Dr (line 20) | function Dr(){this.__data__=[],this.size=0}
  function Ur (line 20) | function Ur(t){var e=this.__data__,n=ci(e,t);if(n<0)return!1;var r=e.len...
  function zr (line 20) | function zr(t){var e=this.__data__,n=ci(e,t);return n<0?o:e[n][1]}
  function qr (line 20) | function qr(t){return ci(this.__data__,t)>-1}
  function Nr (line 20) | function Nr(t,e){var n=this.__data__,r=ci(n,t);return r<0?(++this.size,n...
  function Fr (line 20) | function Fr(t){var e=-1,n=null==t?0:t.length;this.clear();while(++e<n){v...
  function Hr (line 20) | function Hr(){this.size=0,this.__data__={hash:new $r,map:new(Qe||Mr),str...
  function Wr (line 20) | function Wr(t){var e=Wa(this,t)["delete"](t);return this.size-=e?1:0,e}
  function Br (line 20) | function Br(t){return Wa(this,t).get(t)}
  function Kr (line 20) | function Kr(t){return Wa(this,t).has(t)}
  function Vr (line 20) | function Vr(t,e){var n=Wa(this,t),r=n.size;return n.set(t,e),this.size+=...
  function Zr (line 20) | function Zr(t){var e=-1,n=null==t?0:t.length;this.__data__=new Fr;while(...
  function Xr (line 20) | function Xr(t){return this.__data__.set(t,l),this}
  function Gr (line 20) | function Gr(t){return this.__data__.has(t)}
  function Jr (line 20) | function Jr(t){var e=this.__data__=new Mr(t);this.size=e.size}
  function Yr (line 20) | function Yr(){this.__data__=new Mr,this.size=0}
  function Qr (line 20) | function Qr(t){var e=this.__data__,n=e["delete"](t);return this.size=e.s...
  function ti (line 20) | function ti(t){return this.__data__.get(t)}
  function ei (line 20) | function ei(t){return this.__data__.has(t)}
  function ni (line 20) | function ni(t,e){var n=this.__data__;if(n instanceof Mr){var r=n.__data_...
  function ri (line 20) | function ri(t,e){var n=al(t),r=!n&&ol(t),i=!n&&!r&&fl(t),o=!n&&!r&&!i&&U...
  function ii (line 20) | function ii(t){var e=t.length;return e?t[go(0,e-1)]:o}
  function oi (line 20) | function oi(t,e){return Eu(ra(t),vi(e,0,t.length))}
  function ai (line 20) | function ai(t){return Eu(ra(t))}
  function ui (line 20) | function ui(t,e,n){(n===o||nl(t[e],n))&&(n!==o||e in t)||hi(t,e,n)}
  function si (line 20) | function si(t,e,n){var r=t[e];fe.call(t,e)&&nl(r,n)&&(n!==o||e in t)||hi...
  function ci (line 20) | function ci(t,e){var n=t.length;while(n--)if(nl(t[n][0],e))return n;retu...
  function li (line 20) | function li(t,e,n,r){return wi(t,function(t,i,o){e(r,t,n(t),o)}),r}
  function fi (line 20) | function fi(t,e){return t&&ia(e,wf(e),t)}
  function pi (line 20) | function pi(t,e){return t&&ia(e,xf(e),t)}
  function hi (line 20) | function hi(t,e,n){"__proto__"==e&&Se?Se(t,e,{configurable:!0,enumerable...
  function di (line 20) | function di(t,e){var r=-1,i=e.length,a=n(i),u=null==t;while(++r<i)a[r]=u...
  function vi (line 20) | function vi(t,e,n){return t===t&&(n!==o&&(t=t<=n?t:n),e!==o&&(t=t>=e?t:e...
  function yi (line 20) | function yi(t,e,n,r,i,a){var u,s=e&h,c=e&d,l=e&v;if(n&&(u=i?n(t,r,i,a):n...
  function gi (line 20) | function gi(t){var e=wf(t);return function(n){return _i(n,t,e)}}
  function _i (line 20) | function _i(t,e,n){var r=n.length;if(null==t)return!r;t=ne(t);while(r--)...
  function mi (line 20) | function mi(t,e,n){if("function"!=typeof t)throw new oe(c);return ku(fun...
  function bi (line 20) | function bi(t,e,n,r){var i=-1,o=On,a=!0,s=t.length,c=[],l=e.length;if(!s...
  function ki (line 20) | function ki(t,e){var n=!0;return wi(t,function(t,r,i){return n=!!e(t,r,i...
  function Ai (line 20) | function Ai(t,e,n){var r=-1,i=t.length;while(++r<i){var a=t[r],u=e(a);if...
  function Oi (line 20) | function Oi(t,e,n,r){var i=t.length;n=Kl(n),n<0&&(n=-n>i?0:i+n),r=r===o|...
  function Ci (line 20) | function Ci(t,e){var n=[];return wi(t,function(t,r,i){e(t,r,i)&&n.push(t...
  function Ei (line 20) | function Ei(t,e,n,r,i){var o=-1,a=t.length;n||(n=iu),i||(i=[]);while(++o...
  function $i (line 20) | function $i(t,e){return t&&ji(t,e,wf)}
  function Ti (line 20) | function Ti(t,e){return t&&Si(t,e,wf)}
  function Ri (line 20) | function Ri(t,e){return An(e,function(e){return ml(t[e])})}
  function Li (line 20) | function Li(t,e){e=Ho(e,t);var n=0,r=e.length;while(null!=t&&n<r)t=t[Su(...
  function Ii (line 20) | function Ii(t,e,n){var r=e(t);return al(t)?r:jn(r,n(t))}
  function Pi (line 20) | function Pi(t){return null==t?t===o?st:tt:je&&je in ne(t)?Va(t):_u(t)}
  function Mi (line 20) | function Mi(t,e){return t>e}
  function Di (line 20) | function Di(t,e){return null!=t&&fe.call(t,e)}
  function Ui (line 20) | function Ui(t,e){return null!=t&&e in ne(t)}
  function zi (line 20) | function zi(t,e,n){return t>=Ne(e,n)&&t<qe(e,n)}
  function qi (line 20) | function qi(t,e,r){var i=r?Cn:On,a=t[0].length,u=t.length,s=u,c=n(u),l=1...
  function Ni (line 20) | function Ni(t,e,n,r){return $i(t,function(t,i,o){e(r,n(t),i,o)}),r}
  function Fi (line 20) | function Fi(t,e,n){e=Ho(e,t),t=bu(t,e);var r=null==t?t:t[Su(rs(e))];retu...
  function Hi (line 20) | function Hi(t){return kl(t)&&Pi(t)==H}
  function Wi (line 20) | function Wi(t){return kl(t)&&Pi(t)==ft}
  function Bi (line 20) | function Bi(t){return kl(t)&&Pi(t)==V}
  function Ki (line 20) | function Ki(t,e,n,r,i){return t===e||(null==t||null==e||!kl(t)&&!kl(e)?t...
  function Vi (line 20) | function Vi(t,e,n,r,i,o){var a=al(t),u=al(e),s=a?W:Ga(t),c=u?W:Ga(e);s=s...
  function Zi (line 20) | function Zi(t){return kl(t)&&Ga(t)==Y}
  function Xi (line 20) | function Xi(t,e,n,r){var i=n.length,a=i,u=!r;if(null==t)return!a;t=ne(t)...
  function Gi (line 20) | function Gi(t){if(!xl(t)||lu(t))return!1;var e=ml(t)?ge:Xt;return e.test...
  function Ji (line 20) | function Ji(t){return kl(t)&&Pi(t)==it}
  function Yi (line 20) | function Yi(t){return kl(t)&&Ga(t)==ot}
  function Qi (line 20) | function Qi(t){return kl(t)&&wl(t.length)&&!!Ge[Pi(t)]}
  function to (line 20) | function to(t){return"function"==typeof t?t:null==t?Sp:"object"==typeof ...
  function eo (line 20) | function eo(t){if(!pu(t))return ze(t);var e=[];for(var n in ne(t))fe.cal...
  function no (line 20) | function no(t){if(!xl(t))return gu(t);var e=pu(t),n=[];for(var r in t)("...
  function ro (line 20) | function ro(t,e){return t<e}
  function io (line 20) | function io(t,e){var r=-1,i=sl(t)?n(t.length):[];return wi(t,function(t,...
  function oo (line 20) | function oo(t){var e=Ba(t);return 1==e.length&&e[0][2]?du(e[0][0],e[0][1...
  function ao (line 20) | function ao(t,e){return uu(t)&&hu(e)?du(Su(t),e):function(n){var r=vf(n,...
  function uo (line 20) | function uo(t,e,n,r,i){t!==e&&ji(e,function(a,u){if(xl(a))i||(i=new Jr),...
  function so (line 20) | function so(t,e,n,r,i,a,u){var s=lr(t,n),c=lr(e,n),l=u.get(c);if(l)ui(t,...
  function co (line 20) | function co(t,e){var n=t.length;if(n)return e+=e<0?n:0,ou(e,n)?t[e]:o}
  function lo (line 20) | function lo(t,e,n){var r=-1;e=En(e.length?e:[Sp],Zn(Ha()));var i=io(t,fu...
  function fo (line 20) | function fo(t,e){return po(t,e,function(e,n){return gf(t,n)})}
  function po (line 20) | function po(t,e,n){var r=-1,i=e.length,o={};while(++r<i){var a=e[r],u=Li...
  function ho (line 20) | function ho(t){return function(e){return Li(e,t)}}
  function vo (line 20) | function vo(t,e,n,r){var i=r?Un:Dn,o=-1,a=e.length,u=t;t===e&&(e=ra(e)),...
  function yo (line 20) | function yo(t,e){var n=t?e.length:0,r=n-1;while(n--){var i=e[n];if(n==r|...
  function go (line 20) | function go(t,e){return t+Ie(Ke()*(e-t+1))}
  function _o (line 20) | function _o(t,e,r,i){var o=-1,a=qe(Le((e-t)/(r||1)),0),u=n(a);while(a--)...
  function mo (line 20) | function mo(t,e){var n="";if(!t||e<1||e>M)return n;do{e%2&&(n+=t),e=Ie(e...
  function bo (line 20) | function bo(t,e){return Au(mu(t,e,Sp),t+"")}
  function wo (line 20) | function wo(t){return ii(qf(t))}
  function xo (line 20) | function xo(t,e){var n=qf(t);return Eu(n,vi(e,0,n.length))}
  function ko (line 20) | function ko(t,e,n,r){if(!xl(t))return t;e=Ho(e,t);var i=-1,a=e.length,u=...
  function Co (line 20) | function Co(t){return Eu(qf(t))}
  function Eo (line 20) | function Eo(t,e,r){var i=-1,o=t.length;e<0&&(e=-e>o?0:o+e),r=r>o?o:r,r<0...
  function jo (line 20) | function jo(t,e){var n;return wi(t,function(t,r,i){return n=e(t,r,i),!n}...
  function So (line 20) | function So(t,e,n){var r=0,i=null==t?r:t.length;if("number"==typeof e&&e...
  function $o (line 20) | function $o(t,e,n,r){e=n(e);var i=0,a=null==t?0:t.length,u=e!==e,s=null=...
  function To (line 20) | function To(t,e){var n=-1,r=t.length,i=0,o=[];while(++n<r){var a=t[n],u=...
  function Ro (line 20) | function Ro(t){return"number"==typeof t?t:Dl(t)?U:+t}
  function Lo (line 20) | function Lo(t){if("string"==typeof t)return t;if(al(t))return En(t,Lo)+"...
  function Io (line 20) | function Io(t,e,n){var r=-1,i=On,o=t.length,a=!0,s=[],c=s;if(n)a=!1,i=Cn...
  function Po (line 20) | function Po(t,e){return e=Ho(e,t),t=bu(t,e),null==t||delete t[Su(rs(e))]}
  function Mo (line 20) | function Mo(t,e,n,r){return ko(t,e,n(Li(t,e)),r)}
  function Do (line 20) | function Do(t,e,n,r){var i=t.length,o=r?i:-1;while((r?o--:++o<i)&&e(t[o]...
  function Uo (line 20) | function Uo(t,e){var n=t;return n instanceof Cr&&(n=n.value()),Sn(e,func...
  function zo (line 20) | function zo(t,e,r){var i=t.length;if(i<2)return i?Io(t[0]):[];var o=-1,a...
  function qo (line 20) | function qo(t,e,n){var r=-1,i=t.length,a=e.length,u={};while(++r<i){var ...
  function No (line 20) | function No(t){return cl(t)?t:[]}
  function Fo (line 20) | function Fo(t){return"function"==typeof t?t:Sp}
  function Ho (line 20) | function Ho(t,e){return al(t)?t:uu(t,e)?[t]:ju(Jl(t))}
  function Bo (line 20) | function Bo(t,e,n){var r=t.length;return n=n===o?r:n,!e&&n>=r?t:Eo(t,e,n)}
  function Vo (line 20) | function Vo(t,e){if(e)return t.slice();var n=t.length,r=we?we(n):new t.c...
  function Zo (line 20) | function Zo(t){var e=new t.constructor(t.byteLength);return new be(e).se...
  function Xo (line 20) | function Xo(t,e){var n=e?Zo(t.buffer):t.buffer;return new t.constructor(...
  function Go (line 20) | function Go(t){var e=new t.constructor(t.source,Kt.exec(t));return e.las...
  function Jo (line 20) | function Jo(t){return _r?ne(_r.call(t)):{}}
  function Yo (line 20) | function Yo(t,e){var n=e?Zo(t.buffer):t.buffer;return new t.constructor(...
  function Qo (line 20) | function Qo(t,e){if(t!==e){var n=t!==o,r=null===t,i=t===t,a=Dl(t),u=e!==...
  function ta (line 20) | function ta(t,e,n){var r=-1,i=t.criteria,o=e.criteria,a=i.length,u=n.len...
  function ea (line 20) | function ea(t,e,r,i){var o=-1,a=t.length,u=r.length,s=-1,c=e.length,l=qe...
  function na (line 20) | function na(t,e,r,i){var o=-1,a=t.length,u=-1,s=r.length,c=-1,l=e.length...
  function ra (line 20) | function ra(t,e){var r=-1,i=t.length;e||(e=n(i));while(++r<i)e[r]=t[r];r...
  function ia (line 20) | function ia(t,e,n,r){var i=!n;n||(n={});var a=-1,u=e.length;while(++a<u)...
  function oa (line 20) | function oa(t,e){return ia(t,Za(t),e)}
  function aa (line 20) | function aa(t,e){return ia(t,Xa(t),e)}
  function ua (line 20) | function ua(t,e){return function(n,r){var i=al(n)?bn:li,o=e?e():{};retur...
  function sa (line 20) | function sa(t){return bo(function(e,n){var r=-1,i=n.length,a=i>1?n[i-1]:...
  function ca (line 20) | function ca(t,e){return function(n,r){if(null==n)return n;if(!sl(n))retu...
  function la (line 20) | function la(t){return function(e,n,r){var i=-1,o=ne(e),a=r(e),u=a.length...
  function fa (line 20) | function fa(t,e,n){var r=e&_,i=da(t);function o(){var e=this&&this!==un&...
  function pa (line 20) | function pa(t){return function(e){e=Jl(e);var n=ir(e)?yr(e):o,r=n?n[0]:e...
  function ha (line 20) | function ha(t){return function(e){return Sn(bp(Vf(e).replace(Fe,"")),t,"...
  function da (line 20) | function da(t){return function(){var e=arguments;switch(e.length){case 0...
  function va (line 20) | function va(t,e,r){var i=da(t);function a(){var u=arguments.length,s=n(u...
  function ya (line 20) | function ya(t){return function(e,n,r){var i=ne(e);if(!sl(e)){var a=Ha(n,...
  function ga (line 20) | function ga(t){return Da(function(e){var n=e.length,r=n,i=Or.prototype.t...
  function _a (line 20) | function _a(t,e,r,i,a,u,s,c,l,f){var p=e&O,h=e&_,d=e&m,v=e&(w|x),y=e&E,g...
  function ma (line 20) | function ma(t,e){return function(n,r){return Ni(n,t,e(r),{})}}
  function ba (line 20) | function ba(t,e){return function(n,r){var i;if(n===o&&r===o)return e;if(...
  function wa (line 20) | function wa(t){return Da(function(e){return e=En(e,Zn(Ha())),bo(function...
  function xa (line 20) | function xa(t,e){e=e===o?" ":Lo(e);var n=e.length;if(n<2)return n?mo(e,t...
  function ka (line 20) | function ka(t,e,r,i){var o=e&_,a=da(t);function u(){var e=-1,s=arguments...
  function Aa (line 20) | function Aa(t){return function(e,n,r){return r&&"number"!=typeof r&&au(e...
  function Oa (line 20) | function Oa(t){return function(e,n){return"string"==typeof e&&"string"==...
  function Ca (line 20) | function Ca(t,e,n,r,i,a,u,s,c,l){var f=e&w,p=f?u:o,h=f?o:u,d=f?a:o,v=f?o...
  function Ea (line 20) | function Ea(t){var e=ee[t];return function(t,n){if(t=Zl(t),n=null==n?0:N...
  function Sa (line 20) | function Sa(t){return function(e){var n=Ga(e);return n==Y?ur(e):n==ot?pr...
  function $a (line 20) | function $a(t,e,n,r,i,a,u,s){var l=e&m;if(!l&&"function"!=typeof t)throw...
  function Ta (line 20) | function Ta(t,e,n,r){return t===o||nl(t,se[n])&&!fe.call(r,n)?e:t}
  function Ra (line 20) | function Ra(t,e,n,r,i,a){return xl(t)&&xl(e)&&(a.set(e,t),uo(t,e,o,Ra,a)...
  function La (line 20) | function La(t){return Rl(t)?o:t}
  function Ia (line 20) | function Ia(t,e,n,r,i,a){var u=n&y,s=t.length,c=e.length;if(s!=c&&!(u&&c...
  function Pa (line 20) | function Pa(t,e,n,r,i,o,a){switch(n){case pt:if(t.byteLength!=e.byteLeng...
  function Ma (line 20) | function Ma(t,e,n,r,i,a){var u=n&y,s=Ua(t),c=s.length,l=Ua(e),f=l.length...
  function Da (line 20) | function Da(t){return Au(mu(t,o,Ku),t+"")}
  function Ua (line 20) | function Ua(t){return Ii(t,wf,Za)}
  function za (line 20) | function za(t){return Ii(t,xf,Xa)}
  function Na (line 20) | function Na(t){var e=t.name+"",n=cn[e],r=fe.call(cn,e)?n.length:0;while(...
  function Fa (line 20) | function Fa(t){var e=fe.call(wr,"placeholder")?wr:t;return e.placeholder}
  function Ha (line 20) | function Ha(){var t=wr.iteratee||$p;return t=t===$p?to:t,arguments.lengt...
  function Wa (line 20) | function Wa(t,e){var n=t.__data__;return su(e)?n["string"==typeof e?"str...
  function Ba (line 20) | function Ba(t){var e=wf(t),n=e.length;while(n--){var r=e[n],i=t[r];e[n]=...
  function Ka (line 20) | function Ka(t,e){var n=rr(t,e);return Gi(n)?n:o}
  function Va (line 20) | function Va(t){var e=fe.call(t,je),n=t[je];try{t[je]=o;var r=!0}catch(t)...
  function Ja (line 20) | function Ja(t,e,n){var r=-1,i=n.length;while(++r<i){var o=n[r],a=o.size;...
  function Ya (line 20) | function Ya(t){var e=t.match(Nt);return e?e[1].split(Ft):[]}
  function Qa (line 20) | function Qa(t,e,n){e=Ho(e,t);var r=-1,i=e.length,o=!1;while(++r<i){var a...
  function tu (line 20) | function tu(t){var e=t.length,n=new t.constructor(e);return e&&"string"=...
  function eu (line 20) | function eu(t){return"function"!=typeof t.constructor||pu(t)?{}:kr(xe(t))}
  function nu (line 20) | function nu(t,e,n){var r=t.constructor;switch(e){case ft:return Zo(t);ca...
  function ru (line 20) | function ru(t,e){var n=e.length;if(!n)return t;var r=n-1;return e[r]=(n>...
  function iu (line 20) | function iu(t){return al(t)||ol(t)||!!(Ce&&t&&t[Ce])}
  function ou (line 20) | function ou(t,e){var n=typeof t;return e=null==e?M:e,!!e&&("number"==n||...
  function au (line 20) | function au(t,e,n){if(!xl(n))return!1;var r=typeof e;return!!("number"==...
  function uu (line 20) | function uu(t,e){if(al(t))return!1;var n=typeof t;return!("number"!=n&&"...
  function su (line 20) | function su(t){var e=typeof t;return"string"==e||"number"==e||"symbol"==...
  function cu (line 20) | function cu(t){var e=Na(t),n=wr[e];if("function"!=typeof n||!(e in Cr.pr...
  function lu (line 20) | function lu(t){return!!he&&he in t}
  function pu (line 20) | function pu(t){var e=t&&t.constructor,n="function"==typeof e&&e.prototyp...
  function hu (line 20) | function hu(t){return t===t&&!xl(t)}
  function du (line 20) | function du(t,e){return function(n){return null!=n&&(n[t]===e&&(e!==o||t...
  function vu (line 20) | function vu(t){var e=Uc(t,function(t){return n.size===f&&n.clear(),t}),n...
  function yu (line 20) | function yu(t,e){var n=t[1],r=e[1],i=n|r,o=i<(_|m|O),a=r==O&&n==w||r==O&...
  function gu (line 20) | function gu(t){var e=[];if(null!=t)for(var n in ne(t))e.push(n);return e}
  function _u (line 20) | function _u(t){return de.call(t)}
  function mu (line 20) | function mu(t,e,r){return e=qe(e===o?t.length-1:e,0),function(){var i=ar...
  function bu (line 20) | function bu(t,e){return e.length<2?t:Li(t,Eo(e,0,-1))}
  function wu (line 20) | function wu(t,e){var n=t.length,r=Ne(e.length,n),i=ra(t);while(r--){var ...
  function Ou (line 20) | function Ou(t,e,n){var r=e+"";return Au(t,ru(r,Tu(Ya(r),n)))}
  function Cu (line 20) | function Cu(t){var e=0,n=0;return function(){var r=We(),i=T-(r-n);if(n=r...
  function Eu (line 20) | function Eu(t,e){var n=-1,r=t.length,i=r-1;e=e===o?r:e;while(++n<e){var ...
  function Su (line 20) | function Su(t){if("string"==typeof t||Dl(t))return t;var e=t+"";return"0...
  function $u (line 20) | function $u(t){if(null!=t){try{return le.call(t)}catch(t){}try{return t+...
  function Tu (line 20) | function Tu(t,e){return wn(F,function(n){var r="_."+n[0];e&n[1]&&!On(t,r...
  function Ru (line 20) | function Ru(t){if(t instanceof Cr)return t.clone();var e=new Or(t.__wrap...
  function Lu (line 20) | function Lu(t,e,r){e=(r?au(t,e,r):e===o)?1:qe(Kl(e),0);var i=null==t?0:t...
  function Iu (line 20) | function Iu(t){var e=-1,n=null==t?0:t.length,r=0,i=[];while(++e<n){var o...
  function Pu (line 20) | function Pu(){var t=arguments.length;if(!t)return[];var e=n(t-1),r=argum...
  function zu (line 20) | function zu(t,e,n){var r=null==t?0:t.length;return r?(e=n||e===o?1:Kl(e)...
  function qu (line 20) | function qu(t,e,n){var r=null==t?0:t.length;return r?(e=n||e===o?1:Kl(e)...
  function Nu (line 20) | function Nu(t,e){return t&&t.length?Do(t,Ha(e,3),!0,!0):[]}
  function Fu (line 20) | function Fu(t,e){return t&&t.length?Do(t,Ha(e,3),!0):[]}
  function Hu (line 20) | function Hu(t,e,n,r){var i=null==t?0:t.length;return i?(n&&"number"!=typ...
  function Wu (line 20) | function Wu(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=null==n...
  function Bu (line 20) | function Bu(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=r-1;ret...
  function Ku (line 20) | function Ku(t){var e=null==t?0:t.length;return e?Ei(t,1):[]}
  function Vu (line 20) | function Vu(t){var e=null==t?0:t.length;return e?Ei(t,P):[]}
  function Zu (line 20) | function Zu(t,e){var n=null==t?0:t.length;return n?(e=e===o?1:Kl(e),Ei(t...
  function Xu (line 20) | function Xu(t){var e=-1,n=null==t?0:t.length,r={};while(++e<n){var i=t[e...
  function Gu (line 20) | function Gu(t){return t&&t.length?t[0]:o}
  function Ju (line 20) | function Ju(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=null==n...
  function Yu (line 20) | function Yu(t){var e=null==t?0:t.length;return e?Eo(t,0,-1):[]}
  function ns (line 20) | function ns(t,e){return null==t?"":Ue.call(t,e)}
  function rs (line 20) | function rs(t){var e=null==t?0:t.length;return e?t[e-1]:o}
  function is (line 20) | function is(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=r;retur...
  function os (line 20) | function os(t,e){return t&&t.length?co(t,Kl(e)):o}
  function us (line 20) | function us(t,e){return t&&t.length&&e&&e.length?vo(t,e):t}
  function ss (line 20) | function ss(t,e,n){return t&&t.length&&e&&e.length?vo(t,e,Ha(n,2)):t}
  function cs (line 20) | function cs(t,e,n){return t&&t.length&&e&&e.length?vo(t,e,o,n):t}
  function fs (line 20) | function fs(t,e){var n=[];if(!t||!t.length)return n;var r=-1,i=[],o=t.le...
  function ps (line 20) | function ps(t){return null==t?t:Ve.call(t)}
  function hs (line 20) | function hs(t,e,n){var r=null==t?0:t.length;return r?(n&&"number"!=typeo...
  function ds (line 20) | function ds(t,e){return So(t,e)}
  function vs (line 20) | function vs(t,e,n){return $o(t,e,Ha(n,2))}
  function ys (line 20) | function ys(t,e){var n=null==t?0:t.length;if(n){var r=So(t,e);if(r<n&&nl...
  function gs (line 20) | function gs(t,e){return So(t,e,!0)}
  function _s (line 20) | function _s(t,e,n){return $o(t,e,Ha(n,2),!0)}
  function ms (line 20) | function ms(t,e){var n=null==t?0:t.length;if(n){var r=So(t,e,!0)-1;if(nl...
  function bs (line 20) | function bs(t){return t&&t.length?To(t):[]}
  function ws (line 20) | function ws(t,e){return t&&t.length?To(t,Ha(e,2)):[]}
  function xs (line 20) | function xs(t){var e=null==t?0:t.length;return e?Eo(t,1,e):[]}
  function ks (line 20) | function ks(t,e,n){return t&&t.length?(e=n||e===o?1:Kl(e),Eo(t,0,e<0?0:e...
  function As (line 20) | function As(t,e,n){var r=null==t?0:t.length;return r?(e=n||e===o?1:Kl(e)...
  function Os (line 20) | function Os(t,e){return t&&t.length?Do(t,Ha(e,3),!1,!0):[]}
  function Cs (line 20) | function Cs(t,e){return t&&t.length?Do(t,Ha(e,3)):[]}
  function $s (line 20) | function $s(t){return t&&t.length?Io(t):[]}
  function Ts (line 20) | function Ts(t,e){return t&&t.length?Io(t,Ha(e,2)):[]}
  function Rs (line 20) | function Rs(t,e){return e="function"==typeof e?e:o,t&&t.length?Io(t,o,e)...
  function Ls (line 20) | function Ls(t){if(!t||!t.length)return[];var e=0;return t=An(t,function(...
  function Is (line 20) | function Is(t,e){if(!t||!t.length)return[];var n=Ls(t);return null==e?n:...
  function qs (line 20) | function qs(t,e){return qo(t||[],e||[],si)}
  function Ns (line 20) | function Ns(t,e){return qo(t||[],e||[],ko)}
  function Hs (line 20) | function Hs(t){var e=wr(t);return e.__chain__=!0,e}
  function Ws (line 20) | function Ws(t,e){return e(t),t}
  function Bs (line 20) | function Bs(t,e){return e(t)}
  function Vs (line 20) | function Vs(){return Hs(this)}
  function Zs (line 20) | function Zs(){return new Or(this.value(),this.__chain__)}
  function Xs (line 20) | function Xs(){this.__values__===o&&(this.__values__=Wl(this.value()));va...
  function Gs (line 20) | function Gs(){return this}
  function Js (line 20) | function Js(t){var e,n=this;while(n instanceof Ar){var r=Ru(n);r.__index...
  function Ys (line 20) | function Ys(){var t=this.__wrapped__;if(t instanceof Cr){var e=t;return ...
  function Qs (line 20) | function Qs(){return Uo(this.__wrapped__,this.__actions__)}
  function ec (line 20) | function ec(t,e,n){var r=al(t)?kn:ki;return n&&au(t,e,n)&&(e=o),r(t,Ha(e...
  function nc (line 20) | function nc(t,e){var n=al(t)?An:Ci;return n(t,Ha(e,3))}
  function oc (line 20) | function oc(t,e){return Ei(dc(t,e),1)}
  function ac (line 20) | function ac(t,e){return Ei(dc(t,e),P)}
  function uc (line 20) | function uc(t,e,n){return n=n===o?1:Kl(n),Ei(dc(t,e),n)}
  function sc (line 20) | function sc(t,e){var n=al(t)?wn:wi;return n(t,Ha(e,3))}
  function cc (line 20) | function cc(t,e){var n=al(t)?xn:xi;return n(t,Ha(e,3))}
  function fc (line 20) | function fc(t,e,n,r){t=sl(t)?t:qf(t),n=n&&!r?Kl(n):0;var i=t.length;retu...
  function dc (line 20) | function dc(t,e){var n=al(t)?En:io;return n(t,Ha(e,3))}
  function vc (line 20) | function vc(t,e,n,r){return null==t?[]:(al(e)||(e=null==e?[]:[e]),n=r?o:...
  function gc (line 20) | function gc(t,e,n){var r=al(t)?Sn:Hn,i=arguments.length<3;return r(t,Ha(...
  function _c (line 20) | function _c(t,e,n){var r=al(t)?$n:Hn,i=arguments.length<3;return r(t,Ha(...
  function mc (line 20) | function mc(t,e){var n=al(t)?An:Ci;return n(t,zc(Ha(e,3)))}
  function bc (line 20) | function bc(t){var e=al(t)?ii:wo;return e(t)}
  function wc (line 20) | function wc(t,e,n){e=(n?au(t,e,n):e===o)?1:Kl(e);var r=al(t)?oi:xo;retur...
  function xc (line 20) | function xc(t){var e=al(t)?ai:Co;return e(t)}
  function kc (line 20) | function kc(t){if(null==t)return 0;if(sl(t))return Ml(t)?vr(t):t.length;...
  function Ac (line 20) | function Ac(t,e,n){var r=al(t)?Tn:jo;return n&&au(t,e,n)&&(e=o),r(t,Ha(e...
  function Ec (line 20) | function Ec(t,e){if("function"!=typeof e)throw new oe(c);return t=Kl(t),...
  function jc (line 20) | function jc(t,e,n){return e=n?o:e,e=t&&null==e?t.length:e,$a(t,O,o,o,o,o...
  function Sc (line 20) | function Sc(t,e){var n;if("function"!=typeof e)throw new oe(c);return t=...
  function Rc (line 20) | function Rc(t,e,n){e=n?o:e;var r=$a(t,w,o,o,o,o,o,e);return r.placeholde...
  function Lc (line 20) | function Lc(t,e,n){e=n?o:e;var r=$a(t,x,o,o,o,o,o,e);return r.placeholde...
  function Ic (line 20) | function Ic(t,e,n){var r,i,a,u,s,l,f=0,p=!1,h=!1,d=!0;if("function"!=typ...
  function Dc (line 20) | function Dc(t){return $a(t,E)}
  function Uc (line 20) | function Uc(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)...
  function zc (line 20) | function zc(t){if("function"!=typeof t)throw new oe(c);return function()...
  function qc (line 20) | function qc(t){return Sc(2,t)}
  function Bc (line 20) | function Bc(t,e){if("function"!=typeof t)throw new oe(c);return e=e===o?...
  function Kc (line 20) | function Kc(t,e){if("function"!=typeof t)throw new oe(c);return e=null==...
  function Vc (line 20) | function Vc(t,e,n){var r=!0,i=!0;if("function"!=typeof t)throw new oe(c)...
  function Zc (line 20) | function Zc(t){return jc(t,1)}
  function Xc (line 20) | function Xc(t,e){return Fc(Fo(e),t)}
  function Gc (line 20) | function Gc(){if(!arguments.length)return[];var t=arguments[0];return al...
  function Jc (line 20) | function Jc(t){return yi(t,v)}
  function Yc (line 20) | function Yc(t,e){return e="function"==typeof e?e:o,yi(t,v,e)}
  function Qc (line 20) | function Qc(t){return yi(t,h|v)}
  function tl (line 20) | function tl(t,e){return e="function"==typeof e?e:o,yi(t,h|v,e)}
  function el (line 20) | function el(t,e){return null==e||_i(t,e,wf(e))}
  function nl (line 20) | function nl(t,e){return t===e||t!==t&&e!==e}
  function sl (line 20) | function sl(t){return null!=t&&wl(t.length)&&!ml(t)}
  function cl (line 20) | function cl(t){return kl(t)&&sl(t)}
  function ll (line 20) | function ll(t){return!0===t||!1===t||kl(t)&&Pi(t)==K}
  function hl (line 20) | function hl(t){return kl(t)&&1===t.nodeType&&!Rl(t)}
  function dl (line 20) | function dl(t){if(null==t)return!0;if(sl(t)&&(al(t)||"string"==typeof t|...
  function vl (line 20) | function vl(t,e){return Ki(t,e)}
  function yl (line 20) | function yl(t,e,n){n="function"==typeof n?n:o;var r=n?n(t,e):o;return r=...
  function gl (line 20) | function gl(t){if(!kl(t))return!1;var e=Pi(t);return e==X||e==Z||"string...
  function _l (line 20) | function _l(t){return"number"==typeof t&&De(t)}
  function ml (line 20) | function ml(t){if(!xl(t))return!1;var e=Pi(t);return e==G||e==J||e==B||e...
  function bl (line 20) | function bl(t){return"number"==typeof t&&t==Kl(t)}
  function wl (line 20) | function wl(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=M}
  function xl (line 20) | function xl(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}
  function kl (line 20) | function kl(t){return null!=t&&"object"==typeof t}
  function Ol (line 20) | function Ol(t,e){return t===e||Xi(t,e,Ba(e))}
  function Cl (line 20) | function Cl(t,e,n){return n="function"==typeof n?n:o,Xi(t,e,Ba(e),n)}
  function El (line 20) | function El(t){return Tl(t)&&t!=+t}
  function jl (line 20) | function jl(t){if(fu(t))throw new i(s);return Gi(t)}
  function Sl (line 20) | function Sl(t){return null===t}
  function $l (line 20) | function $l(t){return null==t}
  function Tl (line 20) | function Tl(t){return"number"==typeof t||kl(t)&&Pi(t)==Q}
  function Rl (line 20) | function Rl(t){if(!kl(t)||Pi(t)!=et)return!1;var e=xe(t);if(null===e)ret...
  function Il (line 20) | function Il(t){return bl(t)&&t>=-M&&t<=M}
  function Ml (line 20) | function Ml(t){return"string"==typeof t||!al(t)&&kl(t)&&Pi(t)==at}
  function Dl (line 20) | function Dl(t){return"symbol"==typeof t||kl(t)&&Pi(t)==ut}
  function zl (line 20) | function zl(t){return t===o}
  function ql (line 20) | function ql(t){return kl(t)&&Ga(t)==ct}
  function Nl (line 20) | function Nl(t){return kl(t)&&Pi(t)==lt}
  function Wl (line 20) | function Wl(t){if(!t)return[];if(sl(t))return Ml(t)?yr(t):ra(t);if(Ee&&t...
  function Bl (line 20) | function Bl(t){if(!t)return 0===t?t:0;if(t=Zl(t),t===P||t===-P){var e=t<...
  function Kl (line 20) | function Kl(t){var e=Bl(t),n=e%1;return e===e?n?e-n:e:0}
  function Vl (line 20) | function Vl(t){return t?vi(Kl(t),0,z):0}
  function Zl (line 20) | function Zl(t){if("number"==typeof t)return t;if(Dl(t))return U;if(xl(t)...
  function Xl (line 20) | function Xl(t){return ia(t,xf(t))}
  function Gl (line 20) | function Gl(t){return t?vi(Kl(t),-M,M):0===t?t:0}
  function Jl (line 20) | function Jl(t){return null==t?"":Lo(t)}
  function rf (line 20) | function rf(t,e){var n=kr(t);return null==e?n:fi(n,e)}
  function uf (line 20) | function uf(t,e){return Pn(t,Ha(e,3),$i)}
  function sf (line 20) | function sf(t,e){return Pn(t,Ha(e,3),Ti)}
  function cf (line 20) | function cf(t,e){return null==t?t:ji(t,Ha(e,3),xf)}
  function lf (line 20) | function lf(t,e){return null==t?t:Si(t,Ha(e,3),xf)}
  function ff (line 20) | function ff(t,e){return t&&$i(t,Ha(e,3))}
  function pf (line 20) | function pf(t,e){return t&&Ti(t,Ha(e,3))}
  function hf (line 20) | function hf(t){return null==t?[]:Ri(t,wf(t))}
  function df (line 20) | function df(t){return null==t?[]:Ri(t,xf(t))}
  function vf (line 20) | function vf(t,e,n){var r=null==t?o:Li(t,e);return r===o?n:r}
  function yf (line 20) | function yf(t,e){return null!=t&&Qa(t,e,Di)}
  function gf (line 20) | function gf(t,e){return null!=t&&Qa(t,e,Ui)}
  function wf (line 20) | function wf(t){return sl(t)?ri(t):eo(t)}
  function xf (line 20) | function xf(t){return sl(t)?ri(t,!0):no(t)}
  function kf (line 20) | function kf(t,e){var n={};return e=Ha(e,3),$i(t,function(t,r,i){hi(n,e(t...
  function Af (line 20) | function Af(t,e){var n={};return e=Ha(e,3),$i(t,function(t,r,i){hi(n,r,e...
  function jf (line 20) | function jf(t,e){return $f(t,zc(Ha(e)))}
  function $f (line 20) | function $f(t,e){if(null==t)return{};var n=En(za(t),function(t){return[t...
  function Tf (line 20) | function Tf(t,e,n){e=Ho(e,t);var r=-1,i=e.length;i||(i=1,t=o);while(++r<...
  function Rf (line 20) | function Rf(t,e,n){return null==t?t:ko(t,e,n)}
  function Lf (line 20) | function Lf(t,e,n,r){return r="function"==typeof r?r:o,null==t?t:ko(t,e,...
  function Mf (line 20) | function Mf(t,e,n){var r=al(t),i=r||fl(t)||Ul(t);if(e=Ha(e,4),null==n){v...
  function Df (line 20) | function Df(t,e){return null==t||Po(t,e)}
  function Uf (line 20) | function Uf(t,e,n){return null==t?t:Mo(t,e,Fo(n))}
  function zf (line 20) | function zf(t,e,n,r){return r="function"==typeof r?r:o,null==t?t:Mo(t,e,...
  function qf (line 20) | function qf(t){return null==t?[]:Xn(t,wf(t))}
  function Nf (line 20) | function Nf(t){return null==t?[]:Xn(t,xf(t))}
  function Ff (line 20) | function Ff(t,e,n){return n===o&&(n=e,e=o),n!==o&&(n=Zl(n),n=n===n?n:0),...
  function Hf (line 20) | function Hf(t,e,n){return e=Bl(e),n===o?(n=e,e=0):n=Bl(n),t=Zl(t),zi(t,e...
  function Wf (line 20) | function Wf(t,e,n){if(n&&"boolean"!=typeof n&&au(t,e,n)&&(e=n=o),n===o&&...
  function Kf (line 20) | function Kf(t){return mp(Jl(t).toLowerCase())}
  function Vf (line 20) | function Vf(t){return t=Jl(t),t&&t.replace(Yt,tr).replace(He,"")}
  function Zf (line 20) | function Zf(t,e,n){t=Jl(t),e=Lo(e);var r=t.length;n=n===o?r:vi(Kl(n),0,r...
  function Xf (line 20) | function Xf(t){return t=Jl(t),t&&jt.test(t)?t.replace(Ct,er):t}
  function Gf (line 20) | function Gf(t){return t=Jl(t),t&&Mt.test(t)?t.replace(Pt,"\\$&"):t}
  function tp (line 20) | function tp(t,e,n){t=Jl(t),e=Kl(e);var r=e?vr(t):0;if(!e||r>=e)return t;...
  function ep (line 20) | function ep(t,e,n){t=Jl(t),e=Kl(e);var r=e?vr(t):0;return e&&r<e?t+xa(e-...
  function np (line 20) | function np(t,e,n){t=Jl(t),e=Kl(e);var r=e?vr(t):0;return e&&r<e?xa(e-r,...
  function rp (line 20) | function rp(t,e,n){return n||null==e?e=0:e&&(e=+e),Be(Jl(t).replace(Ut,"...
  function ip (line 20) | function ip(t,e,n){return e=(n?au(t,e,n):e===o)?1:Kl(e),mo(Jl(t),e)}
  function op (line 20) | function op(){var t=arguments,e=Jl(t[0]);return t.length<3?e:e.replace(t...
  function up (line 20) | function up(t,e,n){return n&&"number"!=typeof n&&au(t,e,n)&&(e=n=o),n=n=...
  function cp (line 20) | function cp(t,e,n){return t=Jl(t),n=null==n?0:vi(Kl(n),0,t.length),e=Lo(...
  function lp (line 20) | function lp(t,e,n){var r=wr.templateSettings;n&&au(t,e,n)&&(e=o),t=Jl(t)...
  function fp (line 20) | function fp(t){return Jl(t).toLowerCase()}
  function pp (line 20) | function pp(t){return Jl(t).toUpperCase()}
  function hp (line 20) | function hp(t,e,n){if(t=Jl(t),t&&(n||e===o))return t.replace(Dt,"");if(!...
  function dp (line 20) | function dp(t,e,n){if(t=Jl(t),t&&(n||e===o))return t.replace(zt,"");if(!...
  function vp (line 20) | function vp(t,e,n){if(t=Jl(t),t&&(n||e===o))return t.replace(Ut,"");if(!...
  function yp (line 20) | function yp(t,e){var n=j,r=S;if(xl(e)){var i="separator"in e?e.separator...
  function gp (line 20) | function gp(t){return t=Jl(t),t&&Et.test(t)?t.replace(Ot,gr):t}
  function bp (line 20) | function bp(t,e,n){return t=Jl(t),e=n?o:e,e===o?or(t)?br(t):In(t):t.matc...
  function kp (line 20) | function kp(t){var e=null==t?0:t.length,n=Ha();return t=e?En(t,function(...
  function Ap (line 20) | function Ap(t){return gi(yi(t,h))}
  function Op (line 20) | function Op(t){return function(){return t}}
  function Cp (line 20) | function Cp(t,e){return null==t||t!==t?e:t}
  function Sp (line 20) | function Sp(t){return t}
  function $p (line 20) | function $p(t){return to("function"==typeof t?t:yi(t,h))}
  function Tp (line 20) | function Tp(t){return oo(yi(t,h))}
  function Rp (line 20) | function Rp(t,e){return ao(t,yi(e,h))}
  function Pp (line 20) | function Pp(t,e,n){var r=wf(e),i=Ri(e,r);null!=n||xl(e)&&(i.length||!r.l...
  function Mp (line 20) | function Mp(){return un._===this&&(un._=ye),this}
  function Dp (line 20) | function Dp(){}
  function Up (line 20) | function Up(t){return t=Kl(t),bo(function(e){return co(e,t)})}
  function Fp (line 20) | function Fp(t){return uu(t)?Nn(Su(t)):ho(t)}
  function Hp (line 20) | function Hp(t){return function(e){return null==t?o:Li(t,e)}}
  function Kp (line 20) | function Kp(){return[]}
  function Vp (line 20) | function Vp(){return!1}
  function Zp (line 20) | function Zp(){return{}}
  function Xp (line 20) | function Xp(){return""}
  function Gp (line 20) | function Gp(){return!0}
  function Jp (line 20) | function Jp(t,e){if(t=Kl(t),t<1||t>M)return[];var n=z,r=Ne(t,z);e=Ha(e),...
  function Yp (line 20) | function Yp(t){return al(t)?En(t,Su):Dl(t)?[t]:ra(ju(Jl(t)))}
  function Qp (line 20) | function Qp(t){var e=++pe;return Jl(t)+e}
  function ih (line 20) | function ih(t){return t&&t.length?Ai(t,Sp,Mi):o}
  function oh (line 20) | function oh(t,e){return t&&t.length?Ai(t,Ha(e,2),Mi):o}
  function ah (line 20) | function ah(t){return qn(t,Sp)}
  function uh (line 20) | function uh(t,e){return qn(t,Ha(e,2))}
  function sh (line 20) | function sh(t){return t&&t.length?Ai(t,Sp,ro):o}
  function ch (line 20) | function ch(t,e){return t&&t.length?Ai(t,Ha(e,2),ro):o}
  function hh (line 20) | function hh(t){return t&&t.length?Bn(t,Sp):0}
  function dh (line 20) | function dh(t,e){return t&&t.length?Bn(t,Ha(e,2)):0}
  function i (line 20) | function i(t){return t._query=[Date.now().toString()],t}
  function r (line 20) | function r(t){if(t)return i(t)}
  function i (line 20) | function i(t){for(var e in r.prototype)t[e]=r.prototype[e];return t}
  function n (line 20) | function n(){this.off(t,n),e.apply(this,arguments)}
  function n (line 20) | function n(){for(var t=3,e=document.createElement("b"),n=e.all||[];e.inn...
  function r (line 20) | function r(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t...
  function i (line 20) | function i(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Ob...
  function o (line 20) | function o(){throw new TypeError("Invalid attempt to spread non-iterable...
  function a (line 20) | function a(t){return r(t)||i(t)||o()}
  function r (line 25) | function r(t,e){0}
  function i (line 25) | function i(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}
  function a (line 25) | function a(t,e){switch(typeof e){case"undefined":return;case"object":ret...
  function u (line 25) | function u(t,e){for(var n in e)t[n]=e[n];return t}
  function h (line 25) | function h(t,e,n){void 0===e&&(e={});var r,i=n||d;try{r=i(t||"")}catch(t...
  function d (line 25) | function d(t){var e={};return t=t.trim().replace(/^(\?|#|&)/,""),t?(t.sp...
  function v (line 25) | function v(t){var e=t?Object.keys(t).map(function(e){var n=t[e];if(void ...
  function g (line 25) | function g(t,e,n,r){var i=r&&r.options.stringifyQuery,o=e.query||{};try{...
  function _ (line 25) | function _(t){if(Array.isArray(t))return t.map(_);if(t&&"object"===typeo...
  function b (line 25) | function b(t){var e=[];while(t)e.unshift(t),t=t.parent;return e}
  function w (line 25) | function w(t,e){var n=t.path,r=t.query;void 0===r&&(r={});var i=t.hash;v...
  function x (line 25) | function x(t,e){return e===m?t===e:!!e&&(t.path&&e.path?t.path.replace(y...
  function k (line 25) | function k(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t...
  function A (line 25) | function A(t,e){return 0===t.path.replace(y,"/").indexOf(e.path.replace(...
  function O (line 25) | function O(t,e){for(var n in e)if(!(n in t))return!1;return!0}
  function $ (line 25) | function $(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&!t.defau...
  function T (line 25) | function T(t){if(t)for(var e,n=0;n<t.length;n++){if(e=t[n],"a"===e.tag)r...
  function R (line 25) | function R(t){if(!R.installed||C!==t){R.installed=!0,C=t;var e=function(...
  function I (line 25) | function I(t,e,n){var r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"=...
  function P (line 25) | function P(t){var e="",n="",r=t.indexOf("#");r>=0&&(e=t.slice(r),t=t.sli...
  function M (line 25) | function M(t){return t.replace(/\/\//g,"/")}
  function W (line 25) | function W(t,e){var n,r=[],i=0,o=0,a="",u=e&&e.delimiter||"/";while(null...
  function B (line 25) | function B(t,e){return Z(W(t,e))}
  function K (line 25) | function K(t){return encodeURI(t).replace(/[\/?#]/g,function(t){return"%...
  function V (line 25) | function V(t){return encodeURI(t).replace(/[?#]/g,function(t){return"%"+...
  function Z (line 25) | function Z(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"=...
  function X (line 25) | function X(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}
  function G (line 25) | function G(t){return t.replace(/([=!:$\/()])/g,"\\$1")}
  function J (line 25) | function J(t,e){return t.keys=e,t}
  function Y (line 25) | function Y(t){return t.sensitive?"":"i"}
  function Q (line 25) | function Q(t,e){var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.l...
  function tt (line 25) | function tt(t,e,n){for(var r=[],i=0;i<t.length;i++)r.push(rt(t[i],e,n).s...
  function et (line 25) | function et(t,e,n){return nt(W(t,n),e,n)}
  function nt (line 25) | function nt(t,e,n){D(e)||(n=e||n,e=[]),n=n||{};for(var r=n.strict,i=!1!=...
  function rt (line 25) | function rt(t,e,n){return D(e)||(n=e||n,e=[]),n=n||{},t instanceof RegEx...
  function ot (line 25) | function ot(t,e,n){try{var r=it[t]||(it[t]=U.compile(t));return r(e||{},...
  function at (line 25) | function at(t,e,n,r){var i=e||[],o=n||Object.create(null),a=r||Object.cr...
  function ut (line 25) | function ut(t,e,n,r,i,o){var a=r.path,u=r.name;var s=r.pathToRegexpOptio...
  function st (line 25) | function st(t,e){var n=U(t,[],e);return n}
  function ct (line 25) | function ct(t,e,n){return n||(t=t.replace(/\/$/,"")),"/"===t[0]?t:null==...
  function lt (line 25) | function lt(t,e,n,r){var i="string"===typeof t?{path:t}:t;if(i.name||i._...
  function ft (line 25) | function ft(t,e){for(var n in e)t[n]=e[n];return t}
  function pt (line 25) | function pt(t,e){var n=at(t),r=n.pathList,i=n.pathMap,o=n.nameMap;functi...
  function ht (line 25) | function ht(t,e,n){var r=e.match(t);if(!r)return!1;if(!n)return!0;for(va...
  function dt (line 25) | function dt(t,e){return I(t,e.parent?e.parent.path:"/",!0)}
  function yt (line 25) | function yt(){window.history.replaceState({key:$t()},""),window.addEvent...
  function gt (line 25) | function gt(t,e,n,r){if(t.app){var i=t.options.scrollBehavior;i&&t.app.$...
  function _t (line 25) | function _t(){var t=$t();t&&(vt[t]={x:window.pageXOffset,y:window.pageYO...
  function mt (line 25) | function mt(){var t=$t();if(t)return vt[t]}
  function bt (line 25) | function bt(t,e){var n=document.documentElement,r=n.getBoundingClientRec...
  function wt (line 25) | function wt(t){return At(t.x)||At(t.y)}
  function xt (line 25) | function xt(t){return{x:At(t.x)?t.x:window.pageXOffset,y:At(t.y)?t.y:win...
  function kt (line 25) | function kt(t){return{x:At(t.x)?t.x:0,y:At(t.y)?t.y:0}}
  function At (line 25) | function At(t){return"number"===typeof t}
  function Ot (line 25) | function Ot(t,e){var n="object"===typeof t;if(n&&"string"===typeof t.sel...
  function St (line 25) | function St(){return Et.now().toFixed(3)}
  function $t (line 25) | function $t(){return jt}
  function Tt (line 25) | function Tt(t){jt=t}
  function Rt (line 25) | function Rt(t,e){_t();var n=window.history;try{e?n.replaceState({key:jt}...
  function Lt (line 25) | function Lt(t){Rt(t,!0)}
  function It (line 25) | function It(t,e,n){var r=function(i){i>=t.length?n():t[i]?e(t[i],functio...
  function Pt (line 25) | function Pt(t){return function(e,n,r){var o=!1,a=0,u=null;Mt(t,function(...
  function Mt (line 25) | function Mt(t,e){return Dt(t.map(function(t){return Object.keys(t.compon...
  function Dt (line 25) | function Dt(t){return Array.prototype.concat.apply([],t)}
  function zt (line 25) | function zt(t){return t.__esModule||Ut&&"Module"===t[Symbol.toStringTag]}
  function qt (line 25) | function qt(t){var e=!1;return function(){var n=[],r=arguments.length;wh...
  function Ft (line 25) | function Ft(t){if(!t)if(L){var e=document.querySelector("base");t=e&&e.g...
  function Ht (line 25) | function Ht(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n<r;n++)if(...
  function Wt (line 25) | function Wt(t,e,n,r){var i=Mt(t,function(t,r,i,o){var a=Bt(t,e);if(a)ret...
  function Bt (line 25) | function Bt(t,e){return"function"!==typeof t&&(t=C.extend(t)),t.options[e]}
  function Kt (line 25) | function Kt(t){return Wt(t,"beforeRouteLeave",Zt,!0)}
  function Vt (line 25) | function Vt(t){return Wt(t,"beforeRouteUpdate",Zt)}
  function Zt (line 25) | function Zt(t,e){if(e)return function(){return t.apply(e,arguments)}}
  function Xt (line 25) | function Xt(t,e,n){return Wt(t,"beforeRouteEnter",function(t,r,i,o){retu...
  function Gt (line 25) | function Gt(t,e,n,r,i){return function(o,a,u){return t(o,a,function(t){u...
  function Jt (line 25) | function Jt(t,e,n,r){e[n]?t(e[n]):r()&&setTimeout(function(){Jt(t,e,n,r)...
  function e (line 25) | function e(e,n){var r=this;t.call(this,e,n);var i=e.options.scrollBehavi...
  function Qt (line 25) | function Qt(t){var e=window.location.pathname;return t&&0===e.indexOf(t)...
  function e (line 25) | function e(e,n,r){t.call(this,e,n),r&&ee(this.base)||ne()}
  function ee (line 25) | function ee(t){var e=Qt(t);if(!/^\/#/.test(e))return window.location.rep...
  function ne (line 25) | function ne(){var t=re();return"/"===t.charAt(0)||(ae("/"+t),!1)}
  function re (line 25) | function re(){var t=window.location.href,e=t.indexOf("#");return-1===e?"...
  function ie (line 25) | function ie(t){var e=window.location.href,n=e.indexOf("#"),r=n>=0?e.slic...
  function oe (line 25) | function oe(t){Ct?Rt(ie(t)):window.location.hash=t}
  function ae (line 25) | function ae(t){Ct?Lt(ie(t)):window.location.replace(ie(t))}
  function e (line 25) | function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}
  function le (line 25) | function le(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t....
  function fe (line 25) | function fe(t,e,n){var r="hash"===n?"#"+e:e;return t?M(t+"/"+r):r}
  function r (line 25) | function r(t){if(Array.isArray(t))return t}
  function i (line 25) | function i(t,e){var n=[],r=!0,i=!1,o=void 0;try{for(var a,u=t[Symbol.ite...
  function o (line 25) | function o(){throw new TypeError("Invalid attempt to destructure non-ite...
  function a (line 25) | function a(t,e){return r(t)||i(t,e)||o()}
  function i (line 25) | function i(t){if(t)return o(t)}
  function o (line 25) | function o(t){for(var e in i.prototype)t[e]=i.prototype[e];return t}
  function n (line 25) | function n(){this._defaults=[]}
  function r (line 25) | function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enume...
  function i (line 25) | function i(t){var e,n;this.promise=new t(function(t,r){if(void 0!==e||vo...
  function i (line 25) | function i(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[...

FILE: web/vue/dist/vendor/d3.js
  function n (line 2) | function n(t){return function(n,e){return Ms(t(n),e)}}
  function e (line 2) | function e(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.f...
  function r (line 2) | function r(t){return t.length}
  function i (line 2) | function i(){}
  function o (line 2) | function o(t,n){var e=new i;if(t instanceof i)t.each(function(t,n){e.set...
  function u (line 2) | function u(){return{}}
  function a (line 2) | function a(t,n,e){t[n]=e}
  function c (line 2) | function c(){return o()}
  function s (line 2) | function s(t,n,e){t.set(n,e)}
  function f (line 2) | function f(){}
  function l (line 2) | function l(t,n){var e=new f;if(t instanceof f)t.each(function(t){e.add(t...
  function h (line 2) | function h(t){return+t}
  function p (line 2) | function p(t){return t*t}
  function d (line 2) | function d(t){return t*(2-t)}
  function v (line 2) | function v(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}
  function _ (line 2) | function _(t){return t*t*t}
  function y (line 2) | function y(t){return--t*t*t+1}
  function g (line 2) | function g(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}
  function m (line 2) | function m(t){return 1-Math.cos(t*Tf)}
  function x (line 2) | function x(t){return Math.sin(t*Tf)}
  function b (line 2) | function b(t){return(1-Math.cos(Mf*t))/2}
  function w (line 2) | function w(t){return Math.pow(2,10*t-10)}
  function M (line 2) | function M(t){return 1-Math.pow(2,-10*t)}
  function T (line 2) | function T(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t)...
  function N (line 2) | function N(t){return 1-Math.sqrt(1-t*t)}
  function k (line 2) | function k(t){return Math.sqrt(1- --t*t)}
  function S (line 2) | function S(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+...
  function A (line 2) | function A(t){return 1-E(1-t)}
  function E (line 2) | function E(t){return(t=+t)<Nf?Lf*t*t:t<Sf?Lf*(t-=kf)*t+Af:t<Cf?Lf*(t-=Ef...
  function C (line 2) | function C(t){return((t*=2)<=1?1-E(1-t):E(t-1)+1)/2}
  function z (line 2) | function z(t,n){return t[0]-n[0]||t[1]-n[1]}
  function P (line 2) | function P(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&Wf(t...
  function q (line 2) | function q(){this._x0=this._y0=this._x1=this._y1=null,this._=[]}
  function L (line 2) | function L(){return new q}
  function R (line 2) | function R(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h...
  function U (line 2) | function U(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0...
  function D (line 2) | function D(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this}
  function O (line 2) | function O(t){return t[0]}
  function F (line 2) | function F(t){return t[1]}
  function I (line 2) | function I(t,n,e){var r=new Y(null==n?O:n,null==e?F:e,NaN,NaN,NaN,NaN);r...
  function Y (line 2) | function Y(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._...
  function B (line 2) | function B(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.dat...
  function j (line 2) | function j(t){if(!(t>=1))throw new Error;this._size=t,this._call=this._e...
  function H (line 2) | function H(t){if(!t._start)try{X(t)}catch(n){if(t._tasks[t._ended+t._act...
  function X (line 2) | function X(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._end...
  function V (line 2) | function V(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ende...
  function W (line 2) | function W(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t....
  function $ (line 2) | function $(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._ca...
  function Z (line 2) | function Z(t){return new j(arguments.length?+t:1/0)}
  function G (line 2) | function G(t){return t.innerRadius}
  function J (line 2) | function J(t){return t.outerRadius}
  function Q (line 2) | function Q(t){return t.startAngle}
  function K (line 2) | function K(t){return t.endAngle}
  function tt (line 2) | function tt(t){return t&&t.padAngle}
  function nt (line 2) | function nt(t){return t>=1?xl:t<=-1?-xl:Math.asin(t)}
  function et (line 2) | function et(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t...
  function rt (line 2) | function rt(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/Math.sqrt(a*a+c*c)...
  function it (line 2) | function it(t){this._context=t}
  function ot (line 2) | function ot(t){return t[0]}
  function ut (line 2) | function ut(t){return t[1]}
  function at (line 2) | function at(t){this._curve=t}
  function ct (line 2) | function ct(t){function n(n){return new at(t(n))}return n._curve=t,n}
  function st (line 2) | function st(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,...
  function ft (line 2) | function ft(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t...
  function lt (line 2) | function lt(t){this._context=t}
  function ht (line 2) | function ht(t){this._context=t}
  function pt (line 2) | function pt(t){this._context=t}
  function dt (line 2) | function dt(t,n){this._basis=new lt(t),this._beta=n}
  function vt (line 2) | function vt(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._...
  function _t (line 2) | function _t(t,n){this._context=t,this._k=(1-n)/6}
  function yt (line 2) | function yt(t,n){this._context=t,this._k=(1-n)/6}
  function gt (line 2) | function gt(t,n){this._context=t,this._k=(1-n)/6}
  function mt (line 2) | function mt(t,n,e){var r=t._x1,i=t._y1,o=t._x2,u=t._y2;if(t._l01_a>gl){v...
  function xt (line 2) | function xt(t,n){this._context=t,this._alpha=n}
  function bt (line 2) | function bt(t,n){this._context=t,this._alpha=n}
  function wt (line 2) | function wt(t,n){this._context=t,this._alpha=n}
  function Mt (line 2) | function Mt(t){this._context=t}
  function Tt (line 2) | function Tt(t){return t<0?-1:1}
  function Nt (line 2) | function Nt(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&...
  function kt (line 2) | function kt(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}
  function St (line 2) | function St(t,n,e){var r=t._x0,i=t._y0,o=t._x1,u=t._y1,a=(o-r)/3;t._cont...
  function At (line 2) | function At(t){this._context=t}
  function Et (line 2) | function Et(t){this._context=new Ct(t)}
  function Ct (line 2) | function Ct(t){this._context=t}
  function zt (line 2) | function zt(t){return new At(t)}
  function Pt (line 2) | function Pt(t){return new Et(t)}
  function qt (line 2) | function qt(t){this._context=t}
  function Lt (line 2) | function Lt(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),u=new ...
  function Rt (line 2) | function Rt(t,n){this._context=t,this._t=n}
  function Ut (line 2) | function Ut(t){return new Rt(t,0)}
  function Dt (line 2) | function Dt(t){return new Rt(t,1)}
  function Ot (line 2) | function Ot(t,n){return t[n]}
  function Ft (line 2) | function Ft(t){for(var n,e=0,r=-1,i=t.length;++r<i;)(n=+t[r][1])&&(e+=n)...
  function It (line 2) | function It(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[...
  function Yt (line 2) | function Yt(){}
  function Bt (line 2) | function Bt(t){var n;return t=(t+"").trim().toLowerCase(),(n=kh.exec(t))...
  function jt (line 2) | function jt(t){return new Wt(t>>16&255,t>>8&255,255&t,1)}
  function Ht (line 2) | function Ht(t,n,e,r){return r<=0&&(t=n=e=NaN),new Wt(t,n,e,r)}
  function Xt (line 2) | function Xt(t){return t instanceof Yt||(t=Bt(t)),t?(t=t.rgb(),new Wt(t.r...
  function Vt (line 2) | function Vt(t,n,e,r){return 1===arguments.length?Xt(t):new Wt(t,n,e,null...
  function Wt (line 2) | function Wt(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}
  function $t (line 2) | function $t(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=N...
  function Zt (line 2) | function Zt(t){if(t instanceof Jt)return new Jt(t.h,t.s,t.l,t.opacity);i...
  function Gt (line 2) | function Gt(t,n,e,r){return 1===arguments.length?Zt(t):new Jt(t,n,e,null...
  function Jt (line 2) | function Jt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}
  function Qt (line 2) | function Qt(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(...
  function Kt (line 2) | function Kt(t){if(t instanceof nn)return new nn(t.l,t.a,t.b,t.opacity);i...
  function tn (line 2) | function tn(t,n,e,r){return 1===arguments.length?Kt(t):new nn(t,n,e,null...
  function nn (line 2) | function nn(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}
  function en (line 2) | function en(t){return t>Hh?Math.pow(t,1/3):t/jh+Yh}
  function rn (line 2) | function rn(t){return t>Bh?t*t*t:jh*(t-Yh)}
  function on (line 2) | function on(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-....
  function un (line 2) | function un(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}
  function an (line 2) | function an(t){if(t instanceof sn)return new sn(t.h,t.c,t.l,t.opacity);t...
  function cn (line 2) | function cn(t,n,e,r){return 1===arguments.length?an(t):new sn(t,n,e,null...
  function sn (line 2) | function sn(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}
  function fn (line 2) | function fn(t){if(t instanceof hn)return new hn(t.h,t.s,t.l,t.opacity);t...
  function ln (line 2) | function ln(t,n,e,r){return 1===arguments.length?fn(t):new hn(t,n,e,null...
  function hn (line 2) | function hn(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}
  function pn (line 2) | function pn(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u...
  function dn (line 2) | function dn(t,n){return function(e){return t+e*n}}
  function vn (line 2) | function vn(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,functi...
  function _n (line 2) | function _n(t,n){var e=n-t;return e?dn(t,e>180||e<-180?e-360*Math.round(...
  function yn (line 2) | function yn(t){return 1===(t=+t)?gn:function(n,e){return e-n?vn(n,e,t):o...
  function gn (line 2) | function gn(t,n){var e=n-t;return e?dn(t,e):op(isNaN(t)?n:t)}
  function mn (line 2) | function mn(t){return function(n){var e,r,i=n.length,o=new Array(i),u=ne...
  function xn (line 2) | function xn(t){return function(){return t}}
  function bn (line 2) | function bn(t){return function(n){return t(n)+""}}
  function wn (line 2) | function wn(t){return"none"===t?mp:(Kh||(Kh=document.createElement("DIV"...
  function Mn (line 2) | function Mn(t){return null==t?mp:(ep||(ep=document.createElementNS("http...
  function Tn (line 2) | function Tn(t,n,e,r){function i(t){return t.length?t.pop()+" ":""}functi...
  function Nn (line 2) | function Nn(t){return((t=Math.exp(t))+1/t)/2}
  function kn (line 2) | function kn(t){return((t=Math.exp(t))-1/t)/2}
  function Sn (line 2) | function Sn(t){return((t=Math.exp(2*t))-1)/(t+1)}
  function An (line 2) | function An(t){return function(n,e){var r=t((n=Gt(n)).h,(e=Gt(e)).h),i=g...
  function En (line 2) | function En(t,n){var e=gn((t=tn(t)).l,(n=tn(n)).l),r=gn(t.a,n.a),i=gn(t....
  function Cn (line 2) | function Cn(t){return function(n,e){var r=t((n=cn(n)).h,(e=cn(e)).h),i=g...
  function zn (line 2) | function zn(t){return function n(e){function r(n,r){var i=t((n=ln(n)).h,...
  function Pn (line 2) | function Pn(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=argu...
  function qn (line 2) | function qn(t){this._=t}
  function Ln (line 2) | function Ln(t,n){return t.trim().split(/^|\s+/).map(function(t){var e=""...
  function Rn (line 2) | function Rn(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)r...
  function Un (line 2) | function Un(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]...
  function Dn (line 2) | function Dn(t){return new Function("d","return {"+t.map(function(t,n){re...
  function On (line 2) | function On(t,n){var e=Dn(t);return function(r,i){return n(e(r),i,t)}}
  function Fn (line 2) | function Fn(t){var n=Object.create(null),e=[];return t.forEach(function(...
  function In (line 2) | function In(t){return function(n,e){t(null==n?e:null)}}
  function Yn (line 2) | function Yn(t){var n=t.responseType;return n&&"text"!==n?t.response:t.re...
  function Bn (line 2) | function Bn(t,n){return function(e){return t(e.responseText,n)}}
  function jn (line 2) | function jn(){return sd||(hd(Hn),sd=ld.now()+fd)}
  function Hn (line 2) | function Hn(){sd=0}
  function Xn (line 2) | function Xn(){this._call=this._time=this._next=null}
  function Vn (line 2) | function Vn(t,n,e){var r=new Xn;return r.restart(t,n,e),r}
  function Wn (line 2) | function Wn(){jn(),++id;for(var t,n=Up;n;)(t=sd-n._time)>=0&&n._call.cal...
  function $n (line 2) | function $n(){sd=(cd=ld.now())+fd,id=od=0;try{Wn()}finally{id=0,Gn(),sd=0}}
  function Zn (line 2) | function Zn(){var t=ld.now(),n=t-cd;n>ad&&(fd-=n,cd=t)}
  function Gn (line 2) | function Gn(){for(var t,n,e=Up,r=1/0;e;)e._call?(r>e._time&&(r=e._time),...
  function Jn (line 2) | function Jn(t){if(!id){od&&(od=clearTimeout(od));var n=t-sd;n>24?(t<1/0&...
  function Qn (line 2) | function Qn(t,n,e,r){function i(n){return t(n=new Date(+n)),n}return i.f...
  function Kn (line 2) | function Kn(t){return Qn(function(n){n.setDate(n.getDate()-(n.getDay()+7...
  function te (line 2) | function te(t){return Qn(function(n){n.setUTCDate(n.getUTCDate()-(n.getU...
  function ne (line 2) | function ne(t){if(!(n=Av.exec(t)))throw new Error("invalid format: "+t);...
  function ee (line 2) | function ee(t){return t}
  function re (line 2) | function re(n){return Cv=Pv(n),t.format=Cv.format,t.formatPrefix=Cv.form...
  function ie (line 2) | function ie(t){if(0<=t.y&&t.y<100){var n=new Date(-1,t.m,t.d,t.H,t.M,t.S...
  function oe (line 2) | function oe(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t....
  function ue (line 2) | function ue(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}
  function ae (line 2) | function ae(t){function n(t,n){return function(e){var r,i,o,u=[],a=-1,c=...
  function ce (line 2) | function ce(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o...
  function se (line 2) | function se(t){return t.replace(Iv,"\\$&")}
  function fe (line 2) | function fe(t){return new RegExp("^(?:"+t.map(se).join("|")+")","i")}
  function le (line 2) | function le(t){for(var n={},e=-1,r=t.length;++e<r;)n[t[e].toLowerCase()]...
  function he (line 2) | function he(t,n,e){var r=Ov.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r...
  function pe (line 2) | function pe(t,n,e){var r=Ov.exec(n.slice(e));return r?(t.U=+r[0],e+r[0]....
  function de (line 2) | function de(t,n,e){var r=Ov.exec(n.slice(e));return r?(t.W=+r[0],e+r[0]....
  function ve (line 2) | function ve(t,n,e){var r=Ov.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r...
  function _e (line 2) | function _e(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r...
  function ye (line 2) | function ye(t,n,e){var r=/^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(n.slice(e,...
  function ge (line 2) | function ge(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+...
  function me (line 2) | function me(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r...
  function xe (line 2) | function xe(t,n,e){var r=Ov.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[...
  function be (line 2) | function be(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r...
  function we (line 2) | function we(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r...
  function Me (line 2) | function Me(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r...
  function Te (line 2) | function Te(t,n,e){var r=Ov.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r...
  function Ne (line 2) | function Ne(t,n,e){var r=Fv.exec(n.slice(e,e+1));return r?e+r[0].length:-1}
  function ke (line 2) | function ke(t,n){return ce(t.getDate(),n,2)}
  function Se (line 2) | function Se(t,n){return ce(t.getHours(),n,2)}
  function Ae (line 2) | function Ae(t,n){return ce(t.getHours()%12||12,n,2)}
  function Ee (line 2) | function Ee(t,n){return ce(1+Cd.count($d(t),t),n,3)}
  function Ce (line 2) | function Ce(t,n){return ce(t.getMilliseconds(),n,3)}
  function ze (line 2) | function ze(t,n){return ce(t.getMonth()+1,n,2)}
  function Pe (line 2) | function Pe(t,n){return ce(t.getMinutes(),n,2)}
  function qe (line 2) | function qe(t,n){return ce(t.getSeconds(),n,2)}
  function Le (line 2) | function Le(t,n){return ce(Pd.count($d(t),t),n,2)}
  function Re (line 2) | function Re(t){return t.getDay()}
  function Ue (line 2) | function Ue(t,n){return ce(qd.count($d(t),t),n,2)}
  function De (line 2) | function De(t,n){return ce(t.getFullYear()%100,n,2)}
  function Oe (line 2) | function Oe(t,n){return ce(t.getFullYear()%1e4,n,4)}
  function Fe (line 2) | function Fe(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+c...
  function Ie (line 2) | function Ie(t,n){return ce(t.getUTCDate(),n,2)}
  function Ye (line 2) | function Ye(t,n){return ce(t.getUTCHours(),n,2)}
  function Be (line 2) | function Be(t,n){return ce(t.getUTCHours()%12||12,n,2)}
  function je (line 2) | function je(t,n){return ce(1+tv.count(gv(t),t),n,3)}
  function He (line 2) | function He(t,n){return ce(t.getUTCMilliseconds(),n,3)}
  function Xe (line 2) | function Xe(t,n){return ce(t.getUTCMonth()+1,n,2)}
  function Ve (line 2) | function Ve(t,n){return ce(t.getUTCMinutes(),n,2)}
  function We (line 2) | function We(t,n){return ce(t.getUTCSeconds(),n,2)}
  function $e (line 2) | function $e(t,n){return ce(ev.count(gv(t),t),n,2)}
  function Ze (line 2) | function Ze(t){return t.getUTCDay()}
  function Ge (line 2) | function Ge(t,n){return ce(rv.count(gv(t),t),n,2)}
  function Je (line 2) | function Je(t,n){return ce(t.getUTCFullYear()%100,n,2)}
  function Qe (line 2) | function Qe(t,n){return ce(t.getUTCFullYear()%1e4,n,4)}
  function Ke (line 2) | function Ke(){return"+0000"}
  function tr (line 2) | function tr(){return"%"}
  function nr (line 2) | function nr(n){return qv=ae(n),t.timeFormat=qv.format,t.timeParse=qv.par...
  function er (line 2) | function er(t){return t.toISOString()}
  function rr (line 2) | function rr(t){var n=new Date(t);return isNaN(n)?null:n}
  function ir (line 2) | function ir(t){function n(n){var o=n+"",u=e.get(o);if(!u){if(i!==Wv)retu...
  function or (line 2) | function or(){function t(){var t=i().length,r=u[1]<u[0],l=u[r-0],h=u[1-r...
  function ur (line 2) | function ur(t){var n=t.copy;return t.padding=t.paddingOuter,delete t.pad...
  function ar (line 2) | function ar(){return ur(or().paddingInner(1))}
  function cr (line 2) | function cr(t,n){return(n-=t=+t)?function(e){return(e-t)/n}:$v(n)}
  function sr (line 2) | function sr(t){return function(n,e){var r=t(n=+n,e=+e);return function(t...
  function fr (line 2) | function fr(t){return function(n,e){var r=t(n=+n,e=+e);return function(t...
  function lr (line 2) | function lr(t,n,e,r){var i=t[0],o=t[1],u=n[0],a=n[1];return o<i?(i=e(o,i...
  function hr (line 2) | function hr(t,n,e,r){var i=Math.min(t.length,n.length)-1,o=new Array(i),...
  function pr (line 2) | function pr(t,n){return n.domain(t.domain()).range(t.range()).interpolat...
  function dr (line 2) | function dr(t,n){function e(){return i=Math.min(a.length,c.length)>2?hr:...
  function vr (line 2) | function vr(t){var n=t.domain;return t.ticks=function(t){var e=n();retur...
  function _r (line 2) | function _r(){var t=dr(cr,lp);return t.copy=function(){return pr(t,_r())...
  function yr (line 2) | function yr(){function t(t){return+t}var n=[0,1];return t.invert=t,t.dom...
  function gr (line 2) | function gr(t,n){return(n=Math.log(n/t))?function(e){return Math.log(e/t...
  function mr (line 2) | function mr(t,n){return t<0?function(e){return-Math.pow(-n,e)*Math.pow(-...
  function xr (line 2) | function xr(t){return isFinite(t)?+("1e"+t):t<0?0:t}
  function br (line 2) | function br(t){return 10===t?xr:t===Math.E?Math.exp:function(n){return M...
  function wr (line 2) | function wr(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Mat...
  function Mr (line 2) | function Mr(t){return function(n){return-t(-n)}}
  function Tr (line 2) | function Tr(){function n(){return o=wr(i),u=br(i),r()[0]<0&&(o=Mr(o),u=M...
  function Nr (line 2) | function Nr(t,n){return t<0?-Math.pow(-t,n):Math.pow(t,n)}
  function kr (line 2) | function kr(){function t(t,n){return(n=Nr(n,e)-(t=Nr(t,e)))?function(r){...
  function Sr (line 2) | function Sr(){return kr().exponent(.5)}
  function Ar (line 2) | function Ar(){function t(){var t=0,o=Math.max(1,r.length);for(i=new Arra...
  function Er (line 2) | function Er(){function t(t){if(t<=t)return u[ks(o,t,0,i)]}function n(){v...
  function Cr (line 2) | function Cr(){function t(t){if(t<=t)return e[ks(n,t,0,r)]}var n=[.5],e=[...
  function zr (line 2) | function zr(t){return new Date(t);
  function Pr (line 3) | function Pr(t){return t instanceof Date?+t:+new Date(+t)}
  function qr (line 3) | function qr(t,n,r,i,o,u,a,c,s){function f(e){return(a(e)<e?v:u(e)<e?_:o(...
  function Lr (line 3) | function Lr(t){var n=t.length;return function(e){return t[Math.max(0,Mat...
  function Rr (line 3) | function Rr(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Mat...
  function Ur (line 3) | function Ur(t){return function(){var n=this.ownerDocument,e=this.namespa...
  function Dr (line 3) | function Dr(t){return function(){return this.ownerDocument.createElement...
  function Or (line 3) | function Or(){return new Fr}
  function Fr (line 3) | function Fr(){this._="@"+(++k_).toString(36)}
  function Ir (line 3) | function Ir(t,n,e){return t=Yr(t,n,e),function(n){var e=n.relatedTarget;...
  function Yr (line 3) | function Yr(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call...
  function Br (line 3) | function Br(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e...
  function jr (line 3) | function jr(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-...
  function Hr (line 3) | function Hr(t,n,e){var r=z_.hasOwnProperty(t.type)?Ir:Yr;return function...
  function Xr (line 3) | function Xr(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{r...
  function Vr (line 3) | function Vr(){}
  function Wr (line 3) | function Wr(){return[]}
  function $r (line 3) | function $r(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t....
  function Zr (line 3) | function Zr(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=...
  function Gr (line 3) | function Gr(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Ar...
  function Jr (line 3) | function Jr(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}
  function Qr (line 3) | function Qr(t){return function(){this.removeAttribute(t)}}
  function Kr (line 3) | function Kr(t){return function(){this.removeAttributeNS(t.space,t.local)}}
  function ti (line 3) | function ti(t,n){return function(){this.setAttribute(t,n)}}
  function ni (line 3) | function ni(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}
  function ei (line 3) | function ei(t,n){return function(){var e=n.apply(this,arguments);null==e...
  function ri (line 3) | function ri(t,n){return function(){var e=n.apply(this,arguments);null==e...
  function ii (line 3) | function ii(t){return function(){this.style.removeProperty(t)}}
  function oi (line 3) | function oi(t,n,e){return function(){this.style.setProperty(t,n,e)}}
  function ui (line 3) | function ui(t,n,e){return function(){var r=n.apply(this,arguments);null=...
  function ai (line 3) | function ai(t){return function(){delete this[t]}}
  function ci (line 3) | function ci(t,n){return function(){this[t]=n}}
  function si (line 3) | function si(t,n){return function(){var e=n.apply(this,arguments);null==e...
  function fi (line 3) | function fi(t){return t.trim().split(/^|\s+/)}
  function li (line 3) | function li(t){return t.classList||new hi(t)}
  function hi (line 3) | function hi(t){this._node=t,this._names=fi(t.getAttribute("class")||"")}
  function pi (line 3) | function pi(t,n){for(var e=li(t),r=-1,i=n.length;++r<i;)e.add(n[r])}
  function di (line 3) | function di(t,n){for(var e=li(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}
  function vi (line 3) | function vi(t){return function(){pi(this,t)}}
  function _i (line 3) | function _i(t){return function(){di(this,t)}}
  function yi (line 3) | function yi(t,n){return function(){(n.apply(this,arguments)?pi:di)(this,...
  function gi (line 3) | function gi(){this.textContent=""}
  function mi (line 3) | function mi(t){return function(){this.textContent=t}}
  function xi (line 3) | function xi(t){return function(){var n=t.apply(this,arguments);this.text...
  function bi (line 3) | function bi(){this.innerHTML=""}
  function wi (line 3) | function wi(t){return function(){this.innerHTML=t}}
  function Mi (line 3) | function Mi(t){return function(){var n=t.apply(this,arguments);this.inne...
  function Ti (line 3) | function Ti(){this.nextSibling&&this.parentNode.appendChild(this)}
  function Ni (line 3) | function Ni(){this.previousSibling&&this.parentNode.insertBefore(this,th...
  function ki (line 3) | function ki(){return null}
  function Si (line 3) | function Si(){var t=this.parentNode;t&&t.removeChild(this)}
  function Ai (line 3) | function Ai(t,n,e){var r=iy(t),i=r.CustomEvent;i?i=new i(n,e):(i=r.docum...
  function Ei (line 3) | function Ei(t,n){return function(){return Ai(this,t,n)}}
  function Ci (line 3) | function Ci(t,n){return function(){return Ai(this,t,n.apply(this,argumen...
  function zi (line 3) | function zi(t,n){this._groups=t,this._parents=n}
  function Pi (line 3) | function Pi(){return new zi([[document.documentElement]],yy)}
  function qi (line 3) | function qi(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>Ty)throw...
  function Li (line 3) | function Li(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>ky)throw...
  function Ri (line 3) | function Ri(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("...
  function Ui (line 3) | function Ui(t,n,e){function r(t){e.state=Ny,e.timer.restart(i,e.delay,e....
  function Di (line 3) | function Di(t,n){var e,r;return function(){var i=Li(this,t),o=i.tween;if...
  function Oi (line 3) | function Oi(t,n,e){var r,i;if("function"!=typeof e)throw new Error;retur...
  function Fi (line 3) | function Fi(t,n,e){var r=t._id;return t.each(function(){var t=Li(this,r)...
  function Ii (line 3) | function Ii(t){return function(){this.removeAttribute(t)}}
  function Yi (line 3) | function Yi(t){return function(){this.removeAttributeNS(t.space,t.local)}}
  function Bi (line 3) | function Bi(t,n,e){var r,i;return function(){var o=this.getAttribute(t);...
  function ji (line 3) | function ji(t,n,e){var r,i;return function(){var o=this.getAttributeNS(t...
  function Hi (line 3) | function Hi(t,n,e){var r,i,o;return function(){var u,a=e(this);return nu...
  function Xi (line 3) | function Xi(t,n,e){var r,i,o;return function(){var u,a=e(this);return nu...
  function Vi (line 3) | function Vi(t,n){function e(){var e=this,r=n.apply(e,arguments);return r...
  function Wi (line 3) | function Wi(t,n){function e(){var e=this,r=n.apply(e,arguments);return r...
  function $i (line 3) | function $i(t,n){return function(){qi(this,t).delay=+n.apply(this,argume...
  function Zi (line 3) | function Zi(t,n){return n=+n,function(){qi(this,t).delay=n}}
  function Gi (line 3) | function Gi(t,n){return function(){Li(this,t).duration=+n.apply(this,arg...
  function Ji (line 3) | function Ji(t,n){return n=+n,function(){Li(this,t).duration=n}}
  function Qi (line 3) | function Qi(t,n){if("function"!=typeof n)throw new Error;return function...
  function Ki (line 3) | function Ki(t){return(t+"").trim().split(/^|\s+/).every(function(t){var ...
  function to (line 3) | function to(t,n,e){var r,i,o=Ki(n)?qi:Li;return function(){var u=o(this,...
  function no (line 3) | function no(t){return function(){var n=this.parentNode;for(var e in this...
  function eo (line 3) | function eo(t,n){var e,r,i;return function(){var o=iy(this).getComputedS...
  function ro (line 3) | function ro(t){return function(){this.style.removeProperty(t)}}
  function io (line 3) | function io(t,n,e){var r,i;return function(){var o=iy(this).getComputedS...
  function oo (line 3) | function oo(t,n,e){var r,i,o;return function(){var u=iy(this).getCompute...
  function uo (line 3) | function uo(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return...
  function ao (line 3) | function ao(t){return function(){this.textContent=t}}
  function co (line 3) | function co(t){return function(){var n=t(this);this.textContent=null==n?...
  function so (line 3) | function so(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._i...
  function fo (line 3) | function fo(t){return Pi().transition(t)}
  function lo (line 3) | function lo(){return++Ky}
  function ho (line 3) | function ho(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.pare...
  function po (line 3) | function po(t,n,e){var r=t(e);return"translate("+(isFinite(r)?r:n(e))+",...
  function vo (line 3) | function vo(t,n,e){var r=t(e);return"translate(0,"+(isFinite(r)?r:n(e))+...
  function _o (line 3) | function _o(t){var n=t.bandwidth()/2;return t.round()&&(n=Math.round(n))...
  function yo (line 3) | function yo(){return!this.__axis}
  function go (line 3) | function go(t,n){function e(e){var s,f=null==i?n.ticks?n.ticks.apply(n,r...
  function mo (line 3) | function mo(t){return go(ag,t)}
  function xo (line 3) | function xo(t){return go(cg,t)}
  function bo (line 3) | function bo(t){return go(sg,t)}
  function wo (line 3) | function wo(t){return go(fg,t)}
  function Mo (line 3) | function Mo(t,n){return t.parent===n.parent?1:2}
  function To (line 3) | function To(t){return t.reduce(No,0)/t.length}
  function No (line 3) | function No(t,n){return t+n.x}
  function ko (line 3) | function ko(t){return 1+t.reduce(So,0)}
  function So (line 3) | function So(t,n){return Math.max(t,n.y)}
  function Ao (line 3) | function Ao(t){for(var n;n=t.children;)t=n[0];return t}
  function Eo (line 3) | function Eo(t){for(var n;n=t.children;)t=n[n.length-1];return t}
  function Co (line 3) | function Co(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i...
  function zo (line 3) | function zo(t,n){var e,r,i,o,u,a=new Uo(t),c=+t.value&&(a.value=t.value)...
  function Po (line 3) | function Po(){return zo(this).eachBefore(Lo)}
  function qo (line 3) | function qo(t){return t.children}
  function Lo (line 3) | function Lo(t){t.data=t.data.data}
  function Ro (line 3) | function Ro(t){var n=0;do t.height=n;while((t=t.parent)&&t.height<++n)}
  function Uo (line 3) | function Uo(t){this.data=t,this.depth=this.height=0,this.parent=null}
  function Do (line 3) | function Do(t){this._=t,this.next=null}
  function Oo (line 3) | function Oo(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r-n.r;return i*i+1e-6>e*e+r*r}
  function Fo (line 3) | function Fo(t,n){var e,r,i,o=null,u=t.head;switch(n.length){case 1:e=Io(...
  function Io (line 3) | function Io(t){return{x:t.x,y:t.y,r:t.r}}
  function Yo (line 3) | function Yo(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,f=a...
  function Bo (line 3) | function Bo(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,f=e.y,l...
  function jo (line 3) | function jo(t,n,e){var r=t.x,i=t.y,o=n.r+e.r,u=t.r+e.r,a=n.x-r,c=n.y-i,s...
  function Ho (line 3) | function Ho(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i>e*e+r*r}
  function Xo (line 3) | function Xo(t,n,e){var r=t.x-n,i=t.y-e;return r*r+i*i}
  function Vo (line 3) | function Vo(t){this._=t,this.next=null,this.previous=null}
  function Wo (line 3) | function Wo(t){if(!(i=t.length))return 0;var n,e,r,i;if(n=t[0],n.x=0,n.y...
  function $o (line 3) | function $o(t){return null==t?null:Zo(t)}
  function Zo (line 3) | function Zo(t){if("function"!=typeof t)throw new Error;return t}
  function Go (line 3) | function Go(){return 0}
  function Jo (line 3) | function Jo(t){return Math.sqrt(t.value)}
  function Qo (line 3) | function Qo(t){return function(n){n.children||(n.r=Math.max(0,+t(n)||0))}}
  function Ko (line 3) | function Ko(t,n){return function(e){if(r=e.children){var r,i,o,u=r.lengt...
  function tu (line 3) | function tu(t){return function(n){var e=n.parent;n.r*=t,e&&(n.x=e.x+t*n....
  function nu (line 3) | function nu(t){return t.id}
  function eu (line 3) | function eu(t){return t.parentId}
  function ru (line 3) | function ru(t,n){return t.parent===n.parent?1:2}
  function iu (line 3) | function iu(t){var n=t.children;return n?n[0]:t.t}
  function ou (line 3) | function ou(t){var n=t.children;return n?n[n.length-1]:t.t}
  function uu (line 3) | function uu(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}
  function au (line 3) | function au(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)n=i[o],...
  function cu (line 3) | function cu(t,n,e){return t.a.parent===n.parent?t.a:e}
  function su (line 3) | function su(t,n){this._=t,this.parent=null,this.children=null,this.A=nul...
  function fu (line 3) | function fu(t){for(var n,e,r,i,o,u=new su(t,0),a=[u];n=a.pop();)if(r=n._...
  function lu (line 3) | function lu(t,n,e,r,i,o){for(var u,a,c,s,f,l,h,p,d,v,_,y,g=[],m=n.childr...
  function hu (line 3) | function hu(t){return t.x+t.vx}
  function pu (line 3) | function pu(t){return t.y+t.vy}
  function du (line 3) | function du(t,n){return n}
  function vu (line 3) | function vu(t,n){var e=t.get(n);if(!e)throw new Error("missing: "+n);ret...
  function _u (line 3) | function _u(t){return t.x}
  function yu (line 3) | function yu(t){return t.y}
  function gu (line 3) | function gu(){t.event.stopImmediatePropagation()}
  function mu (line 3) | function mu(t,n){var e=t.document.documentElement,r=gy(t).on("dragstart....
  function xu (line 3) | function xu(t,n,e,r,i,o,u,a,c,s){this.target=t,this.type=n,this.subject=...
  function bu (line 3) | function bu(){return!t.event.button}
  function wu (line 3) | function wu(){return this.parentNode}
  function Mu (line 3) | function Mu(n){return null==n?{x:t.event.x,y:t.event.y}:n}
  function Tu (line 3) | function Tu(t){return t[0]}
  function Nu (line 3) | function Nu(t){return t[1]}
  function ku (line 3) | function ku(){this._=null}
  function Su (line 3) | function Su(t){t.U=t.C=t.L=t.R=t.P=t.N=null}
  function Au (line 3) | function Au(t,n){var e=n,r=n.R,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e...
  function Eu (line 3) | function Eu(t,n){var e=n,r=n.L,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e...
  function Cu (line 3) | function Cu(t){for(;t.L;)t=t.L;return t}
  function zu (line 3) | function zu(t,n,e,r){var i=[null,null],o=sm.push(i)-1;return i.left=t,i....
  function Pu (line 3) | function Pu(t,n,e){var r=[n,e];return r.left=t,r}
  function qu (line 3) | function qu(t,n,e,r){t[0]||t[1]?t.left===e?t[1]=r:t[0]=r:(t[0]=r,t.left=...
  function Lu (line 3) | function Lu(t,n,e,r,i){var o,u=t[0],a=t[1],c=u[0],s=u[1],f=a[0],l=a[1],h...
  function Ru (line 3) | function Ru(t,n,e,r,i){var o=t[1];if(o)return!0;var u,a,c=t[0],s=t.left,...
  function Uu (line 3) | function Uu(t,n,e,r){for(var i,o=sm.length;o--;)Ru(i=sm[o],t,n,e,r)&&Lu(...
  function Du (line 3) | function Du(t){return am[t.index]={site:t,halfedges:[]}}
  function Ou (line 3) | function Ou(t,n){var e=t.site,r=n.left,i=n.right;return e===i&&(i=r,r=e)...
  function Fu (line 3) | function Fu(t,n){return n[+(n.left!==t.site)]}
  function Iu (line 3) | function Iu(t,n){return n[+(n.left===t.site)]}
  function Yu (line 3) | function Yu(){for(var t,n,e,r,i=0,o=am.length;i<o;++i)if((t=am[i])&&(r=(...
  function Bu (line 3) | function Bu(t,n,e,r){var i,o,u,a,c,s,f,l,h,p,d,v,_=am.length,y=!0;for(i=...
  function ju (line 3) | function ju(){Su(this),this.x=this.y=this.arc=this.site=this.cy=null}
  function Hu (line 3) | function Hu(t){var n=t.P,e=t.N;if(n&&e){var r=n.site,i=t.site,o=e.site;i...
  function Xu (line 3) | function Xu(t){var n=t.circle;n&&(n.P||(om=n.N),cm.remove(n),fm.push(n),...
  function Vu (line 3) | function Vu(){Su(this),this.edge=this.site=this.circle=null}
  function Wu (line 3) | function Wu(t){var n=lm.pop()||new Vu;return n.site=t,n}
  function $u (line 3) | function $u(t){Xu(t),um.remove(t),lm.push(t),Su(t)}
  function Zu (line 3) | function Zu(t){var n=t.circle,e=n.x,r=n.cy,i=[e,r],o=t.P,u=t.N,a=[t];$u(...
  function Gu (line 3) | function Gu(t){for(var n,e,r,i,o=t[0],u=t[1],a=um._;a;)if(r=Ju(a,u)-o,r>...
  function Ju (line 3) | function Ju(t,n){var e=t.site,r=e[0],i=e[1],o=i-n;if(!o)return r;var u=t...
  function Qu (line 3) | function Qu(t,n){var e=t.N;if(e)return Ju(e,n);var r=t.site;return r[1]=...
  function Ku (line 3) | function Ku(t,n,e){return(t[0]-e[0])*(n[1]-t[1])-(t[0]-n[0])*(e[1]-t[1])}
  function ta (line 3) | function ta(t,n){return n[1]-t[1]||n[0]-t[0]}
  function na (line 3) | function na(t,n){var e,r,i,o=t.sort(ta).pop();for(sm=[],am=new Array(t.l...
  function ea (line 3) | function ea(t,n,e){this.target=t,this.type=n,this.transform=e}
  function ra (line 3) | function ra(t,n,e){this.k=t,this.x=n,this.y=e}
  function ia (line 3) | function ia(t){return t.__zoom||_m}
  function oa (line 3) | function oa(){t.event.stopImmediatePropagation()}
  function ua (line 3) | function ua(){return!t.event.button}
  function aa (line 3) | function aa(){var t,n,e=this;return e instanceof SVGElement?(e=e.ownerSV...
  function ca (line 3) | function ca(){return this.__zoom||_m}
  function sa (line 3) | function sa(){t.event.stopImmediatePropagation()}
  function fa (line 3) | function fa(t){return{type:t}}
  function la (line 3) | function la(){return!t.event.button}
  function ha (line 3) | function ha(){var t=this.ownerSVGElement||this;return[[0,0],[t.width.bas...
  function pa (line 3) | function pa(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__b...
  function da (line 3) | function da(t){return t[0][0]===t[1][0]||t[0][1]===t[1][1]}
  function va (line 3) | function va(t){var n=t.__brush;return n?n.dim.output(n.selection):null}
  function _a (line 3) | function _a(){return ga(km)}
  function ya (line 3) | function ya(){return ga(Sm)}
  function ga (line 3) | function ga(n){function e(t){var e=t.property("__brush",a).selectAll(".o...
  function ma (line 4) | function ma(t){return function(n,e){return t(n.source.value+n.target.val...
  function xa (line 4) | function xa(t){return t.source}
  function ba (line 4) | function ba(t){return t.target}
  function wa (line 4) | function wa(t){return t.radius}
  function Ma (line 4) | function Ma(t){return t.startAngle}
  function Ta (line 4) | function Ta(t){return t.endAngle}
  function Na (line 4) | function Na(){this.reset()}
  function ka (line 4) | function ka(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}
  function Sa (line 4) | function Sa(t){return t>1?0:t<-1?kx:Math.acos(t)}
  function Aa (line 4) | function Aa(t){return t>1?Sx:t<-1?-Sx:Math.asin(t)}
  function Ea (line 4) | function Ea(t){return(t=Ix(t/2))*t}
  function Ca (line 4) | function Ca(){}
  function za (line 4) | function za(t,n){t&&Xx.hasOwnProperty(t.type)&&Xx[t.type](t,n)}
  function Pa (line 4) | function Pa(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[...
  function qa (line 4) | function qa(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)Pa(t[e]...
  function La (line 4) | function La(){Zx.point=Ua}
  function Ra (line 4) | function Ra(){Da(Vm,Wm)}
  function Ua (line 4) | function Ua(t,n){Zx.point=Da,Vm=t,Wm=n,t*=zx,n*=zx,$m=t,Zm=Rx(n=n/2+Ax),...
  function Da (line 4) | function Da(t,n){t*=zx,n*=zx,n=n/2+Ax;var e=t-$m,r=e>=0?1:-1,i=r*e,o=Rx(...
  function Oa (line 4) | function Oa(t){return[Lx(t[1],t[0]),Aa(t[2])]}
  function Fa (line 4) | function Fa(t){var n=t[0],e=t[1],r=Rx(e);return[r*Rx(n),r*Ix(n),Ix(e)]}
  function Ia (line 4) | function Ia(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}
  function Ya (line 4) | function Ya(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1...
  function Ba (line 4) | function Ba(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}
  function ja (line 4) | function ja(t,n){return[t[0]*n,t[1]*n,t[2]*n]}
  function Ha (line 4) | function Ha(t){var n=Bx(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t...
  function Xa (line 4) | function Xa(t,n){ox.push(ux=[Jm=t,Km=t]),n<Qm&&(Qm=n),n>tx&&(tx=n)}
  function Va (line 4) | function Va(t,n){var e=Fa([t*zx,n*zx]);if(ix){var r=Ya(ix,e),i=[r[1],-r[...
  function Wa (line 4) | function Wa(){Qx.point=Va}
  function $a (line 4) | function $a(){ux[0]=Jm,ux[1]=Km,Qx.point=Xa,ix=null}
  function Za (line 4) | function Za(t,n){if(ix){var e=t-nx;Jx.add(Px(e)>180?e+(e>0?360:-360):e)}...
  function Ga (line 4) | function Ga(){Zx.lineStart()}
  function Ja (line 4) | function Ja(){Za(ex,rx),Zx.lineEnd(),Px(Jx)>Tx&&(Jm=-(Km=180)),ux[0]=Jm,...
  function Qa (line 4) | function Qa(t,n){return(n-=t)<0?n+360:n}
  function Ka (line 4) | function Ka(t,n){return t[0]-n[0]}
  function tc (line 4) | function tc(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}
  function nc (line 4) | function nc(t,n){t*=zx,n*=zx;var e=Rx(n);ec(e*Rx(t),e*Ix(t),Ix(n))}
  function ec (line 4) | function ec(t,n,e){++ax,sx+=(t-sx)/ax,fx+=(n-fx)/ax,lx+=(e-lx)/ax}
  function rc (line 4) | function rc(){tb.point=ic}
  function ic (line 4) | function ic(t,n){t*=zx,n*=zx;var e=Rx(n);xx=e*Rx(t),bx=e*Ix(t),wx=Ix(n),...
  function oc (line 4) | function oc(t,n){t*=zx,n*=zx;var e=Rx(n),r=e*Rx(t),i=e*Ix(t),o=Ix(n),u=L...
  function uc (line 4) | function uc(){tb.point=nc}
  function ac (line 4) | function ac(){tb.point=sc}
  function cc (line 4) | function cc(){fc(gx,mx),tb.point=nc}
  function sc (line 4) | function sc(t,n){gx=t,mx=n,t*=zx,n*=zx,tb.point=fc;var e=Rx(n);xx=e*Rx(t...
  function fc (line 4) | function fc(t,n){t*=zx,n*=zx;var e=Rx(n),r=e*Rx(t),i=e*Ix(t),o=Ix(n),u=b...
  function lc (line 4) | function lc(t,n){return[t>kx?t-Ex:t<-kx?t+Ex:t,n]}
  function hc (line 4) | function hc(t,n,e){return(t%=Ex)?n||e?rb(dc(t),vc(n,e)):dc(t):n||e?vc(n,...
  function pc (line 4) | function pc(t){return function(n,e){return n+=t,[n>kx?n-Ex:n<-kx?n+Ex:n,...
  function dc (line 4) | function dc(t){var n=pc(t);return n.invert=pc(-t),n}
  function vc (line 4) | function vc(t,n){function e(t,n){var e=Rx(n),a=Rx(t)*e,c=Ix(t)*e,s=Ix(n)...
  function _c (line 4) | function _c(t,n,e,r,i,o){if(e){var u=Rx(n),a=Ix(n),c=r*e;null==i?(i=n+r*...
  function yc (line 4) | function yc(t,n){n=Fa(n),n[0]-=t,Ha(n);var e=Sa(-n[1]);return((-n[2]<0?-...
  function gc (line 4) | function gc(t,n,e,r){this.x=t,this.z=n,this.o=e,this.e=r,this.v=!1,this....
  function mc (line 4) | function mc(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r<n;)i.n=e=t[r],e...
  function xc (line 4) | function xc(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}funct...
  function bc (line 4) | function bc(){Nb.point=Mc,Nb.lineEnd=wc}
  function wc (line 4) | function wc(){Nb.point=Nb.lineEnd=Ca}
  function Mc (line 4) | function Mc(t,n){t*=zx,n*=zx,ib=t,ob=Ix(n),ub=Rx(n),Nb.point=Tc}
  function Tc (line 4) | function Tc(t,n){t*=zx,n*=zx;var e=Ix(n),r=Rx(n),i=Px(t-ib),o=Rx(i),u=Ix...
  function Nc (line 4) | function Nc(t,n,e){var r=Os(t,n-Tx,e).concat(n);return function(t){retur...
  function kc (line 4) | function kc(t,n,e){var r=Os(t,n-Tx,e).concat(n);return function(t){retur...
  function Sc (line 4) | function Sc(){function t(){return{type:"MultiLineString",coordinates:n()...
  function Ac (line 4) | function Ac(){return Sc()()}
  function Ec (line 4) | function Ec(){Lb.point=Cc}
  function Cc (line 4) | function Cc(t,n){Lb.point=zc,ab=sb=t,cb=fb=n}
  function zc (line 4) | function zc(t,n){qb.add(fb*t-sb*n),sb=t,fb=n}
  function Pc (line 4) | function Pc(){zc(ab,cb)}
  function qc (line 4) | function qc(t,n){t<Rb&&(Rb=t),t>Db&&(Db=t),n<Ub&&(Ub=n),n>Ob&&(Ob=n)}
  function Lc (line 4) | function Lc(t,n){Ib+=t,Yb+=n,++Bb}
  function Rc (line 4) | function Rc(){Zb.point=Uc}
  function Uc (line 4) | function Uc(t,n){Zb.point=Dc,Lc(pb=t,db=n)}
  function Dc (line 4) | function Dc(t,n){var e=t-pb,r=n-db,i=Bx(e*e+r*r);jb+=i*(pb+t)/2,Hb+=i*(d...
  function Oc (line 4) | function Oc(){Zb.point=Lc}
  function Fc (line 4) | function Fc(){Zb.point=Yc}
  function Ic (line 4) | function Ic(){Bc(lb,hb)}
  function Yc (line 4) | function Yc(t,n){Zb.point=Bc,Lc(lb=pb=t,hb=db=n)}
  function Bc (line 4) | function Bc(t,n){var e=t-pb,r=n-db,i=Bx(e*e+r*r);jb+=i*(pb+t)/2,Hb+=i*(d...
  function jc (line 4) | function jc(t){this._context=t}
  function Hc (line 4) | function Hc(){this._string=[]}
  function Xc (line 4) | function Xc(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" ...
  function Vc (line 4) | function Vc(t){return t.length>1}
  function Wc (line 4) | function Wc(t,n){return((t=t.x)[0]<0?t[1]-Sx-Tx:Sx-t[1])-((n=n.x)[0]<0?n...
  function $c (line 4) | function $c(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lin...
  function Zc (line 4) | function Zc(t,n,e,r){var i,o,u=Ix(t-e);return Px(u)>Tx?qx((Ix(n)*(o=Rx(r...
  function Gc (line 4) | function Gc(t,n,e,r){var i;if(null==t)i=e*Sx,r.point(-kx,i),r.point(0,i)...
  function Jc (line 4) | function Jc(t){return function(n){var e=new Qc;for(var r in t)e[r]=t[r];...
  function Qc (line 4) | function Qc(){}
  function Kc (line 4) | function Kc(t,n,e){var r=n[1][0]-n[0][0],i=n[1][1]-n[0][1],o=t.clipExten...
  function ts (line 4) | function ts(t,n,e){return Kc(t,[[0,0],n],e)}
  function ns (line 4) | function ns(t){return Jc({point:function(n,e){n=t(n,e),this.stream.point...
  function es (line 4) | function es(t,n){function e(r,i,o,u,a,c,s,f,l,h,p,d,v,_){var y=s-r,g=f-i...
  function rs (line 4) | function rs(t){return is(function(){return t})()}
  function is (line 4) | function is(t){function n(t){return t=f(t[0]*zx,t[1]*zx),[t[0]*_+a,c-t[1...
  function os (line 4) | function os(t){var n=0,e=kx/3,r=is(t),i=r(n,e);return i.parallels=functi...
  function us (line 4) | function us(t){function n(t,n){return[t*e,Ix(n)/e]}var e=Rx(t);return n....
  function as (line 4) | function as(t,n){function e(t,n){var e=Bx(o-2*i*Ix(n))/i;return[e*Ix(t*=...
  function cs (line 4) | function cs(t){var n=t.length;return{point:function(e,r){for(var i=-1;++...
  function ss (line 4) | function ss(t){return function(n,e){var r=Rx(n),i=Rx(e),o=t(r*i);return[...
  function fs (line 4) | function fs(t){return function(n,e){var r=Bx(n*n+e*e),i=t(r),o=Ix(i),u=R...
  function ls (line 4) | function ls(t,n){return[t,Ox(jx((Sx+n)/2))]}
  function hs (line 4) | function hs(t){var n,e=rs(t),r=e.scale,i=e.translate,o=e.clipExtent;retu...
  function ps (line 4) | function ps(t){return jx((Sx+t)/2)}
  function ds (line 4) | function ds(t,n){function e(t,n){o>0?n<-Sx+Tx&&(n=-Sx+Tx):n>Sx-Tx&&(n=Sx...
  function vs (line 4) | function vs(t,n){return[t,n]}
  function _s (line 4) | function _s(t,n){function e(t,n){var e=o-n,r=i*t;return[e*Ix(r),o-e*Rx(r...
  function ys (line 4) | function ys(t,n){var e=Rx(n),r=Rx(t)*e;return[e*Ix(t)/r,Ix(n)/r]}
  function gs (line 4) | function gs(t,n,e){return 1===t&&0===n&&0===e?zb:Jc({point:function(r,i)...
  function ms (line 4) | function ms(t,n){return[Rx(n)*Ix(t),Ix(n)]}
  function xs (line 4) | function xs(t,n){var e=Rx(n),r=1+Rx(t)*e;return[e*Ix(t)/r,Ix(n)/r]}
  function bs (line 4) | function bs(t,n){return[Ox(jx((Sx+n)/2)),-t]}
  function t (line 4) | function t(t){var i,o,u=t.length,a=new Array(u);for(i=0;i<u;++i)a[i]=n(t...
  function t (line 4) | function t(n,i,u,a){if(i>=f.length)return null!=r?r(n):null!=e?n.sort(e)...
  function n (line 4) | function n(t,e){if(++e>f.length)return t;var i,o=l[e-1];return null!=r&&...
  function e (line 4) | function e(t){return Math.pow(t,n)}
  function e (line 4) | function e(t){return 1-Math.pow(1-t,n)}
  function e (line 4) | function e(t){return((t*=2)<=1?Math.pow(t,n):2-Math.pow(2-t,n))/2}
  function e (line 4) | function e(t){return t*t*((n+1)*t-n)}
  function e (line 4) | function e(t){return--t*t*((n+1)*t+n)+1}
  function e (line 4) | function e(t){return((t*=2)<1?t*t*((n+1)*t-n):(t-=2)*t*((n+1)*t+n)+2)/2}
  function r (line 4) | function r(t){return n*Math.pow(2,10*--t)*Math.sin((i-t)/e)}
  function r (line 4) | function r(t){return 1-n*Math.pow(2,-10*(t=+t))*Math.sin((t+i)/e)}
  function r (line 4) | function r(t){return((t=2*t-1)<0?n*Math.pow(2,10*t)*Math.sin((i-t)/e):2-...
  function t (line 5) | function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,argument...
  function t (line 5) | function t(t){var a,c,s,f=t.length,l=!1;for(null==i&&(u=o(s=L())),a=0;a<...
  function t (line 5) | function t(t){var n,f,l,h,p,d=t.length,v=!1,_=new Array(d),y=new Array(d...
  function n (line 5) | function n(){return Tl().defined(u).curve(c).context(a)}
  function t (line 5) | function t(t){var a,c,s,f,l,h=t.length,p=0,d=new Array(h),v=new Array(h)...
  function t (line 5) | function t(){var t;if(r||(r=t=L()),n.apply(this,arguments).draw(r,+e.app...
  function e (line 5) | function e(t){return 1===n?new lt(t):new dt(t,n)}
  function e (line 5) | function e(t){return new _t(t,n)}
  function e (line 5) | function e(t){return new yt(t,n)}
  function e (line 5) | function e(t){return new gt(t,n)}
  function e (line 5) | function e(t){return n?new xt(t,n):new _t(t,0)}
  function e (line 5) | function e(t){return n?new bt(t,n):new yt(t,0)}
  function e (line 5) | function e(t){return n?new wt(t,n):new gt(t,0)}
  function t (line 5) | function t(t){var o,u,a=n.apply(this,arguments),c=t.length,s=a.length,f=...
  function e (line 5) | function e(t,n){var e=r((t=Vt(t)).r,(n=Vt(n)).r),i=r(t.g,n.g),o=r(t.b,n....
  function n (line 6) | function n(t,n){var r,i,o=e(t,function(t,e){return r?r(t,e-1):(i=t,void(...
  function e (line 6) | function e(t,n){function e(){if(f>=s)return u;if(i)return i=!1,o;var n,e...
  function r (line 6) | function r(n,e){return null==e&&(e=Fn(n)),[e.map(u).join(t)].concat(n.ma...
  function i (line 6) | function i(t){return t.map(o).join("\n")}
  function o (line 6) | function o(n){return n.map(u).join(t)}
  function u (line 6) | function u(t){return null==t?"":a.test(t+="")?'"'+t.replace(/\"/g,'""')+...
  function e (line 6) | function e(t){var n,e=f.status;if(!e&&Yn(f)||e>=200&&e<300||304===e){if(...
  function n (line 6) | function n(t){function n(t){var n,i,c,g=d,m=v;if("c"===p)m=_(t)+m,t="";e...
  function e (line 6) | function e(t,e){var r=n((t=Ev(t),t.type="f",t)),i=3*Math.max(-8,Math.min...
  function n (line 6) | function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}
  function t (line 7) | function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=...
  function t (line 7) | function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(Qo(n)).eachAfter(Ko(...
  function t (line 7) | function t(t){var u=t.height+1;return t.x0=t.y0=i,t.x1=e,t.y1=r/u,t.each...
  function n (line 7) | function n(t,n){return function(e){e.children&&Eg(e,e.x0,t*(e.depth+1)/n...
  function t (line 7) | function t(t){var r,i,o,u,a,c,s,f=t.length,l=new Array(f),h={};for(i=0;i...
  function t (line 7) | function t(t){var r=fu(t);if(r.eachAfter(n),r.parent.m=-r.z,r.eachBefore...
  function n (line 7) | function n(t){var n=t.children,e=t.parent.children,i=t.i?e[t.i-1]:null;i...
  function e (line 7) | function e(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}
  function r (line 7) | function r(t,n,e){if(n){for(var r,i=t,u=t,a=n,c=i.parent.children[0],s=i...
  function i (line 7) | function i(t){t.x*=u,t.y=t.depth*a}
  function e (line 7) | function e(t,e,r,i,o){lu(n,t,e,r,i,o)}
  function t (line 7) | function t(t){return t.x0=t.y0=0,t.x1=i,t.y1=o,t.eachBefore(n),u=[0],r&&...
  function n (line 7) | function n(t){var n=u[t.depth],r=t.x0+n,i=t.y0+n,o=t.x1-n,h=t.y1-n;o<r&&...
  function o (line 7) | function o(t,n,e,r,i,u,a){if(t>=n-1){var s=c[t];return s.x0=r,s.y0=i,s.x...
  function e (line 7) | function e(t,e,r,i,o){if((u=t._squarify)&&u.ratio===n)for(var u,a,c,s,f,...
  function e (line 7) | function e(){var e,i,o=r.length,u=0,a=0;for(e=0;e<o;++e)i=r[e],u+=i.x,a+...
  function n (line 7) | function n(){function t(t,e,r,i,o){var a=t.data,p=t.r,d=l+p;{if(!a)retur...
  function e (line 7) | function e(t){if(t.data)return t.r=o[t.data.index];for(var n=t.r=0;n<4;+...
  function r (line 7) | function r(){if(i){var n,e=i.length;for(o=new Array(e),n=0;n<e;++n)o[n]=...
  function n (line 7) | function n(t){return 1/Math.min(f[t.source.index],f[t.target.index])}
  function e (line 7) | function e(n){for(var e=0,r=t.length;e<v;++e)for(var i,o,u,s,f,h,p,d=0;d...
  function r (line 7) | function r(){if(s){var n,e,r=s.length,p=t.length,d=o(s,h);for(n=0,f=new ...
  function i (line 7) | function i(){if(s)for(var n=0,e=t.length;n<e;++n)a[n]=+p(t[n],n,t)}
  function u (line 7) | function u(){if(s)for(var n=0,e=t.length;n<e;++n)c[n]=+d(t[n],n,t)}
  function n (line 7) | function n(){e(),d.call("tick",u),a<c&&(p.stop(),d.call("end",u))}
  function e (line 7) | function e(){var n,e,r=t.length;for(a+=(f-a)*s,h.each(function(t){t(a)})...
  function r (line 7) | function r(){for(var n,e=0,r=t.length;e<r;++e){if(n=t[e],n.index=e,isNaN...
  function i (line 7) | function i(n){return n.initialize&&n.initialize(t),n}
  function t (line 7) | function t(t){var n,a=i.length,c=I(i,_u,yu).visitAfter(e);for(u=t,n=0;n<...
  function n (line 7) | function n(){if(i){var t,n=i.length;for(a=new Array(n),t=0;t<n;++t)a[t]=...
  function e (line 7) | function e(t){var n,e,r,i,o,u=0;if(t.length){for(r=i=o=0;o<4;++o)(n=t[o]...
  function r (line 7) | function r(t,n,e,r){if(!t.value)return!0;var i=t.x-o.x,c=t.y-o.y,h=r-n,p...
  function n (line 7) | function n(t){for(var n,e=0,u=r.length;e<u;++e)n=r[e],n.vx+=(o[e]-n.x)*i...
  function e (line 7) | function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=...
  function n (line 7) | function n(t){for(var n,e=0,u=r.length;e<u;++e)n=r[e],n.vy+=(o[e]-n.y)*i...
  function e (line 7) | function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=...
  function n (line 7) | function n(t){t.on("mousedown.drag",e).on("touchstart.drag",o).on("touch...
  function e (line 7) | function e(){if(!f&&l.apply(this,arguments)){var n=c("mouse",h.apply(thi...
  function r (line 7) | function r(){tm(),s=!0,d.mouse("drag")}
  function i (line 7) | function i(){gy(t.event.view).on("mousemove.drag mouseup.drag",null),mu(...
  function o (line 7) | function o(){if(l.apply(this,arguments)){var n,e,r=t.event.changedTouche...
  function u (line 7) | function u(){var n,e,r=t.event.changedTouches,i=r.length;for(n=0;n<i;++n...
  function a (line 7) | function a(){var n,e,r=t.event.changedTouches,i=r.length;for(f&&clearTim...
  function c (line 7) | function c(e,r,i,o,u){var a,c,s,f=i(r,e),l=v.copy();if(Xr(new xu(n,"befo...
  function t (line 7) | function t(t){return new na(t.map(function(r,i){var o=[Math.round(n(r,i,...
  function n (line 7) | function n(t){t.on("wheel.zoom",s).on("mousedown.zoom",f).on("dblclick.z...
  function e (line 7) | function e(t,n){return n=Math.max(m,Math.min(x,n)),n===t.k?t:new ra(n,t....
  function r (line 7) | function r(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i=...
  function i (line 7) | function i(t,n){var e=Math.min(0,t.invertX(n[0][0])-b)||Math.max(0,t.inv...
  function o (line 7) | function o(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}
  function u (line 7) | function u(t,n,e){t.on("start.zoom",function(){a(this,arguments).start()...
  function a (line 7) | function a(t,n){for(var e,r=0,i=k.length;r<i;++r)if((e=k[r]).that===t)re...
  function c (line 7) | function c(t,n){this.that=t,this.args=n,this.index=-1,this.active=0,this...
  function s (line 7) | function s(){function n(){o.wheel=null,o.end()}if(y.apply(this,arguments...
  function f (line 7) | function f(){function n(){ym(),o.moved=!0,o.zoom("mouse",i(r(o.that.__zo...
  function l (line 7) | function l(){if(y.apply(this,arguments)){var o=this.__zoom,a=U_(this),c=...
  function h (line 7) | function h(){if(y.apply(this,arguments)){var n,e,r,i=a(this,arguments),o...
  function p (line 7) | function p(){var n,o,u,c,s=a(this,arguments),f=t.event.changedTouches,l=...
  function d (line 7) | function d(){var n,e,r=a(this,arguments),i=t.event.changedTouches,o=i.le...
  function t (line 7) | function t(t){var o,u,a,c,s,f,l=t.length,h=[],p=Os(l),d=[],v=[],_=v.grou...
  function t (line 7) | function t(){var t,a=Bm.call(arguments),c=n.apply(this,a),s=e.apply(this...
  function e (line 8) | function e(e,r){return e=t(e,r),n(e[0],e[1])}
  function n (line 8) | function n(n){return n=t(n[0]*zx,n[1]*zx),n[0]*=Cx,n[1]*=Cx,n}
  function t (line 8) | function t(t,n){e.push(t=r(t,n)),t[0]*=Cx,t[1]*=Cx}
  function n (line 8) | function n(){var t=i.apply(this,arguments),n=o.apply(this,arguments)*zx,...
  function e (line 8) | function e(t){return t&&("function"==typeof o&&i.pointRadius(+o.apply(th...
  function u (line 8) | function u(n,e){var r=i(n,e);t(n=r[0],e=r[1])&&o.point(n,e)}
  function a (line 8) | function a(t,n){var e=i(t,n);_.point(e[0],e[1])}
  function c (line 8) | function c(){b.point=a,_.lineStart()}
  function s (line 8) | function s(){b.point=u,_.lineEnd()}
  function f (line 8) | function f(t,n){v.push([t,n]);var e=i(t,n);m.point(e[0],e[1])}
  function l (line 8) | function l(){m.lineStart(),v=[]}
  function h (line 8) | function h(){f(v[0][0],v[0][1]),m.lineEnd();var t,n,e,r,i=m.clean(),u=g....
  function e (line 8) | function e(e,r,i,o){_c(o,t,n,i,e,r)}
  function r (line 8) | function r(t,n){return Rx(t)*Rx(n)>a}
  function i (line 8) | function i(t){var n,e,i,a,f;return{lineStart:function(){a=i=!1,f=1},poin...
  function o (line 8) | function o(t,n,e){var r=Fa(t),i=Fa(n),o=[1,0,0],u=Ya(r,i),c=Ia(u,u),s=u[...
  function u (line 8) | function u(n,e){var r=c?t:kx-t,i=0;return n<-r?i|=1:n>r&&(i|=2),e<-r?i|=...
  function t (line 8) | function t(t){var n=t[0],e=t[1];return a=null,i.point(n,e),a||(o.point(n...
  function n (line 8) | function n(){return e=r=null,t}
  function t (line 8) | function t(){return i=o=null,u}

FILE: web/vue/dist/vendor/humanize-duration.js
  function humanizer (line 20) | function humanizer (passedOptions) {
  function doHumanization (line 52) | function doHumanization (ms, options) {
  function render (line 138) | function render (count, type, dictionary, options) {
  function extend (line 159) | function extend (destination) {

FILE: web/vue/dist/vendor/moment.js
  function a (line 6) | function a(){return md.apply(null,arguments)}
  function b (line 9) | function b(a){md=a}
  function c (line 9) | function c(a){return a instanceof Array||"[object Array]"===Object.proto...
  function d (line 9) | function d(a){
  function e (line 12) | function e(a){var b;for(b in a)
  function f (line 14) | function f(a){return a instanceof Date||"[object Date]"===Object.prototy...
  function g (line 14) | function g(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));retu...
  function h (line 14) | function h(a,b){return Object.prototype.hasOwnProperty.call(a,b)}
  function i (line 14) | function i(a,b){for(var c in b)h(b,c)&&(a[c]=b[c]);return h(b,"toString"...
  function j (line 14) | function j(a,b,c,d){return qb(a,b,c,d,!0).utc()}
  function k (line 14) | function k(){
  function l (line 16) | function l(a){return null==a._pf&&(a._pf=k()),a._pf}
  function m (line 16) | function m(a){if(null==a._isValid){var b=l(a),c=nd.call(b.parsedDatePart...
  function n (line 16) | function n(a){var b=j(NaN);return null!=a?i(l(b),a):l(b).userInvalidated...
  function o (line 16) | function o(a){return void 0===a}
  function p (line 16) | function p(a,b){var c,d,e;if(o(b._isAMomentObject)||(a._isAMomentObject=...
  function q (line 18) | function q(b){p(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),
  function r (line 21) | function r(a){return a instanceof q||null!=a&&null!=a._isAMomentObject}
  function s (line 21) | function s(a){return a<0?Math.ceil(a)||0:Math.floor(a)}
  function t (line 21) | function t(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=s(b)),c}
  function u (line 23) | function u(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.lengt...
  function v (line 23) | function v(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof co...
  function w (line 23) | function w(b,c){var d=!0;return i(function(){if(null!=a.deprecationHandl...
  function x (line 23) | function x(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),qd...
  function y (line 23) | function y(a){return a instanceof Function||"[object Function]"===Object...
  function z (line 23) | function z(a){var b,c;for(c in a)b=a[c],y(b)?this[c]=b:this["_"+c]=b;thi...
  function A (line 26) | function A(a,b){var c,e=i({},a);for(c in b)h(b,c)&&(d(a[c])&&d(b[c])?(e[...
  function B (line 28) | function B(a){null!=a&&this.set(a)}
  function C (line 28) | function C(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;retur...
  function D (line 28) | function D(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toU...
  function E (line 28) | function E(){return this._invalidDate}
  function F (line 28) | function F(a){return this._ordinal.replace("%d",a)}
  function G (line 28) | function G(a,b,c,d){var e=this._relativeTime[c];return y(e)?e(a,b,c,d):e...
  function H (line 28) | function H(a,b){var c=this._relativeTime[a>0?"future":"past"];return y(c...
  function I (line 28) | function I(a,b){var c=a.toLowerCase();zd[c]=zd[c+"s"]=zd[b]=a}
  function J (line 28) | function J(a){return"string"==typeof a?zd[a]||zd[a.toLowerCase()]:void 0}
  function K (line 28) | function K(a){var b,c,d={};for(c in a)h(a,c)&&(b=J(c),b&&(d[b]=a[c]));re...
  function L (line 28) | function L(a,b){Ad[a]=b}
  function M (line 28) | function M(a){var b=[];for(var c in a)b.push({unit:c,priority:Ad[c]});re...
  function N (line 28) | function N(b,c){return function(d){return null!=d?(P(this,b,d),a.updateO...
  function O (line 28) | function O(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}
  function P (line 28) | function P(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}
  function Q (line 30) | function Q(a){return a=J(a),y(this[a])?this[a]():this}
  function R (line 30) | function R(a,b){if("object"==typeof a){a=K(a);for(var c=M(a),d=0;d<c.len...
  function S (line 30) | function S(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+...
  function T (line 35) | function T(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return thi...
  function U (line 35) | function U(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.repl...
  function V (line 35) | function V(a){var b,c,d=a.match(Bd);for(b=0,c=d.length;b<c;b++)Ed[d[b]]?...
  function W (line 37) | function W(a,b){return a.isValid()?(b=X(b,a.localeData()),Dd[b]=Dd[b]||V...
  function X (line 37) | function X(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(...
  function Y (line 37) | function Y(a,b,c){Wd[a]=y(b)?b:function(a,d){return a&&c?c:b}}
  function Z (line 37) | function Z(a,b){return h(Wd,a)?Wd[a](b._strict,b._locale):new RegExp($(a))}
  function $ (line 39) | function $(a){return _(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]...
  function _ (line 39) | function _(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}
  function aa (line 39) | function aa(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typ...
  function ba (line 39) | function ba(a,b){aa(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}
  function ca (line 39) | function ca(a,b,c){null!=b&&h(Xd,a)&&Xd[a](b,c._a,c,a)}
  function da (line 39) | function da(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}
  function ea (line 39) | function ea(a,b){return a?c(this._months)?this._months[a.month()]:this._...
  function fa (line 39) | function fa(a,b){return a?c(this._monthsShort)?this._monthsShort[a.month...
  function ga (line 39) | function ga(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsPar...
  function ha (line 41) | function ha(a,b,c){var d,e,f;if(this._monthsParseExact)return ga.call(th...
  function ia (line 51) | function ia(a,b){var c;if(!a.isValid())
  function ja (line 55) | function ja(b){return null!=b?(ia(this,b),a.updateOffset(this,!0),this):...
  function ka (line 55) | function ka(){return da(this.year(),this.month())}
  function la (line 55) | function la(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na...
  function ma (line 55) | function ma(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na...
  function na (line 55) | function na(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[]...
  function oa (line 62) | function oa(a){return pa(a)?366:365}
  function pa (line 62) | function pa(a){return a%4===0&&a%100!==0||a%400===0}
  function qa (line 62) | function qa(){return pa(this.year())}
  function ra (line 62) | function ra(a,b,c,d,e,f,g){
  function sa (line 67) | function sa(a){var b=new Date(Date.UTC.apply(null,arguments));
  function ta (line 71) | function ta(a,b,c){var// first-week day -- which january is always in th...
  function ua (line 76) | function ua(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ta(a,d,e),j=1+7*(b-1)+h+i;r...
  function va (line 76) | function va(a,b,c){var d,e,f=ta(a.year(),b,c),g=Math.floor((a.dayOfYear(...
  function wa (line 76) | function wa(a,b,c){var d=ta(a,b,c),e=ta(a+1,b,c);return(oa(a)-d+e)/7}
  function xa (line 79) | function xa(a){return va(a,this._week.dow,this._week.doy).week}
  function ya (line 79) | function ya(){return this._week.dow}
  function za (line 79) | function za(){return this._week.doy}
  function Aa (line 81) | function Aa(a){var b=this.localeData().week(this);return null==a?b:this....
  function Ba (line 81) | function Ba(a){var b=va(this,1,4).week;return null==a?b:this.add(7*(a-b)...
  function Ca (line 83) | function Ca(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(...
  function Da (line 83) | function Da(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(...
  function Ea (line 83) | function Ea(a,b){return a?c(this._weekdays)?this._weekdays[a.day()]:this...
  function Fa (line 83) | function Fa(a){return a?this._weekdaysShort[a.day()]:this._weekdaysShort}
  function Ga (line 83) | function Ga(a){return a?this._weekdaysMin[a.day()]:this._weekdaysMin}
  function Ha (line 83) | function Ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysP...
  function Ia (line 83) | function Ia(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ha.call(...
  function Ja (line 89) | function Ja(a){if(!this.isValid())return null!=a?this:NaN;var b=this._is...
  function Ka (line 89) | function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.da...
  function La (line 89) | function La(a){if(!this.isValid())return null!=a?this:NaN;
  function Ma (line 93) | function Ma(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")...
  function Na (line 93) | function Na(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")...
  function Oa (line 93) | function Oa(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")...
  function Pa (line 93) | function Pa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[...
  function Qa (line 100) | function Qa(){return this.hours()%12||12}
  function Ra (line 100) | function Ra(){return this.hours()||24}
  function Sa (line 100) | function Sa(a,b){T(a,0,0,function(){return this.localeData().meridiem(th...
  function Ta (line 102) | function Ta(a,b){return b._meridiemParse}
  function Ua (line 104) | function Ua(a){
  function Va (line 107) | function Va(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}
  function Wa (line 107) | function Wa(a){return a?a.toLowerCase().replace("_","-"):a}
  function Xa (line 111) | function Xa(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Wa(a[f]).split("-"...
  function Ya (line 113) | function Ya(a){var b=null;
  function Za (line 122) | function Za(a,b){var c;
  function $a (line 124) | function $a(a,b){if(null!==b){var c=ve;
  function _a (line 129) | function _a(a,b){if(null!=b){var c,d=ve;
  function ab (line 137) | function ab(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abb...
  function bb (line 139) | function bb(){return rd(we)}
  function cb (line 139) | function cb(a){var b,c=a._a;return c&&l(a).overflow===-2&&(b=c[Zd]<0||c[...
  function db (line 141) | function db(a){var b,c,d,e,f,g,h=a._i,i=xe.exec(h)||ye.exec(h);if(i){for...
  function eb (line 145) | function eb(b){var c=Ce.exec(b._i);return null!==c?void(b._d=new Date(+c...
  function fb (line 147) | function fb(a,b,c){return null!=a?a:null!=b?b:c}
  function gb (line 147) | function gb(b){
  function hb (line 154) | function hb(a){var b,c,d,e,f=[];if(!a._d){
  function ib (line 171) | function ib(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b...
  function jb (line 184) | function jb(b){
  function kb (line 199) | function kb(a,b,c){var d;
  function lb (line 203) | function lb(a){var b,c,d,e,f;if(0===a._f.length)return l(a).invalidForma...
  function mb (line 207) | function mb(a){if(!a._d){var b=K(a._i);a._a=g([b.year,b.month,b.day||b.d...
  function nb (line 207) | function nb(a){var b=new q(cb(ob(a)));
  function ob (line 209) | function ob(a){var b=a._i,d=a._f;return a._locale=a._locale||ab(a._l),nu...
  function pb (line 209) | function pb(b){var d=b._i;void 0===d?b._d=new Date(a.now()):f(d)?b._d=ne...
  function qb (line 211) | function qb(a,b,f,g,h){var i={};
  function rb (line 214) | function rb(a,b,c,d){return qb(a,b,c,d,!1)}
  function sb (line 220) | function sb(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)re...
  function tb (line 222) | function tb(){var a=[].slice.call(arguments,0);return sb("isBefore",a)}
  function ub (line 222) | function ub(){var a=[].slice.call(arguments,0);return sb("isAfter",a)}
  function vb (line 222) | function vb(a){var b=K(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.we...
  function wb (line 233) | function wb(a){return a instanceof vb}
  function xb (line 233) | function xb(a){return a<0?Math.round(-1*a)*-1:Math.round(a)}
  function yb (line 235) | function yb(a,b){T(a,0,0,function(){var a=this.utcOffset(),c="+";return ...
  function zb (line 235) | function zb(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"")...
  function Ab (line 237) | function Ab(b,c){var d,e;
  function Bb (line 239) | function Bb(a){
  function Cb (line 254) | function Cb(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?(...
  function Db (line 254) | function Db(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffs...
  function Eb (line 254) | function Eb(a){return this.utcOffset(0,a)}
  function Fb (line 254) | function Fb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a...
  function Gb (line 254) | function Gb(){if(this._tzm)this.utcOffset(this._tzm);else if("string"==t...
  function Hb (line 254) | function Hb(a){return!!this.isValid()&&(a=a?rb(a).utcOffset():0,(this.ut...
  function Ib (line 254) | function Ib(){return this.utcOffset()>this.clone().month(0).utcOffset()|...
  function Jb (line 254) | function Jb(){if(!o(this._isDSTShifted))return this._isDSTShifted;var a=...
  function Kb (line 254) | function Kb(){return!!this.isValid()&&!this._isUTC}
  function Lb (line 254) | function Lb(){return!!this.isValid()&&this._isUTC}
  function Mb (line 254) | function Mb(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}
  function Nb (line 254) | function Nb(a,b){var c,d,e,f=a,
  function Ob (line 257) | function Ob(a,b){
  function Pb (line 263) | function Pb(a,b){var c={milliseconds:0,months:0};return c.months=b.month...
  function Qb (line 263) | function Qb(a,b){var c;return a.isValid()&&b.isValid()?(b=Ab(b,a),a.isBe...
  function Rb (line 265) | function Rb(a,b){return function(c,d){var e,f;
  function Sb (line 267) | function Sb(b,c,d,e){var f=c._milliseconds,g=xb(c._days),h=xb(c._months)...
  function Tb (line 267) | function Tb(a,b){var c=a.diff(b,"days",!0);return c<-6?"sameElse":c<-1?"...
  function Ub (line 267) | function Ub(b,c){
  function Vb (line 270) | function Vb(){return new q(this)}
  function Wb (line 270) | function Wb(a,b){var c=r(a)?a:rb(a);return!(!this.isValid()||!c.isValid(...
  function Xb (line 270) | function Xb(a,b){var c=r(a)?a:rb(a);return!(!this.isValid()||!c.isValid(...
  function Yb (line 270) | function Yb(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!thi...
  function Zb (line 270) | function Zb(a,b){var c,d=r(a)?a:rb(a);return!(!this.isValid()||!d.isVali...
  function $b (line 270) | function $b(a,b){return this.isSame(a,b)||this.isAfter(a,b)}
  function _b (line 270) | function _b(a,b){return this.isSame(a,b)||this.isBefore(a,b)}
  function ac (line 270) | function ac(a,b,c){var d,e,f,g;// 1000
  function bc (line 275) | function bc(a,b){
  function cc (line 283) | function cc(){return this.clone().locale("en").format("ddd MMM DD YYYY H...
  function dc (line 283) | function dc(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999...
  function ec (line 283) | function ec(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);va...
  function fc (line 283) | function fc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isVali...
  function gc (line 283) | function gc(a){return this.from(rb(),a)}
  function hc (line 283) | function hc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isVali...
  function ic (line 283) | function ic(a){return this.to(rb(),a)}
  function jc (line 287) | function jc(a){var b;return void 0===a?this._locale._abbr:(b=ab(a),null!...
  function kc (line 287) | function kc(){return this._locale}
  function lc (line 287) | function lc(a){
  function mc (line 298) | function mc(a){
  function nc (line 300) | function nc(){return this._d.valueOf()-6e4*(this._offset||0)}
  function oc (line 300) | function oc(){return Math.floor(this.valueOf()/1e3)}
  function pc (line 300) | function pc(){return new Date(this.valueOf())}
  function qc (line 300) | function qc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.m...
  function rc (line 300) | function rc(){var a=this;return{years:a.year(),months:a.month(),date:a.d...
  function sc (line 300) | function sc(){
  function tc (line 302) | function tc(){return m(this)}
  function uc (line 302) | function uc(){return i({},l(this))}
  function vc (line 302) | function vc(){return l(this).overflow}
  function wc (line 302) | function wc(){return{input:this._i,format:this._f,locale:this._locale,is...
  function xc (line 302) | function xc(a,b){T(0,[a,a.length],0,b)}
  function yc (line 304) | function yc(a){return Cc.call(this,a,this.week(),this.weekday(),this.loc...
  function zc (line 304) | function zc(a){return Cc.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}
  function Ac (line 304) | function Ac(){return wa(this.year(),1,4)}
  function Bc (line 304) | function Bc(){var a=this.localeData()._week;return wa(this.year(),a.dow,...
  function Cc (line 304) | function Cc(a,b,c,d,e){var f;return null==a?va(this,d,e).year:(f=wa(a,d,...
  function Dc (line 304) | function Dc(a,b,c,d,e){var f=ua(a,b,c,d,e),g=sa(f.year,0,f.dayOfYear);re...
  function Ec (line 306) | function Ec(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3...
  function Fc (line 309) | function Fc(a){var b=Math.round((this.clone().startOf("day")-this.clone(...
  function Gc (line 309) | function Gc(a,b){b[ce]=t(1e3*("0."+a))}
  function Hc (line 311) | function Hc(){return this._isUTC?"UTC":""}
  function Ic (line 311) | function Ic(){return this._isUTC?"Coordinated Universal Time":""}
  function Jc (line 311) | function Jc(a){return rb(1e3*a)}
  function Kc (line 311) | function Kc(){return rb.apply(null,arguments).parseZone()}
  function Lc (line 311) | function Lc(a){return a}
  function Mc (line 311) | function Mc(a,b,c,d){var e=ab(),f=j().set(d,b);return e[c](f,a)}
  function Nc (line 311) | function Nc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b...
  function Oc (line 320) | function Oc(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=voi...
  function Pc (line 320) | function Pc(a,b){return Nc(a,b,"months")}
  function Qc (line 320) | function Qc(a,b){return Nc(a,b,"monthsShort")}
  function Rc (line 320) | function Rc(a,b,c){return Oc(a,b,c,"weekdays")}
  function Sc (line 320) | function Sc(a,b,c){return Oc(a,b,c,"weekdaysShort")}
  function Tc (line 320) | function Tc(a,b,c){return Oc(a,b,c,"weekdaysMin")}
  function Uc (line 320) | function Uc(){var a=this._data;return this._milliseconds=Ue(this._millis...
  function Vc (line 320) | function Vc(a,b,c,d){var e=Nb(b,c);return a._milliseconds+=d*e._millisec...
  function Wc (line 322) | function Wc(a,b){return Vc(this,a,b,1)}
  function Xc (line 324) | function Xc(a,b){return Vc(this,a,b,-1)}
  function Yc (line 324) | function Yc(a){return a<0?Math.floor(a):Math.ceil(a)}
  function Zc (line 324) | function Zc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._mo...
  function $c (line 331) | function $c(a){
  function _c (line 334) | function _c(a){
  function ad (line 336) | function ad(a){var b,c,d=this._milliseconds;if(a=J(a),"month"===a||"year...
  function bd (line 342) | function bd(){return this._milliseconds+864e5*this._days+this._months%12...
  function cd (line 342) | function cd(a){return function(){return this.as(a)}}
  function dd (line 342) | function dd(a){return a=J(a),this[a+"s"]()}
  function ed (line 342) | function ed(a){return function(){return this._data[a]}}
  function fd (line 342) | function fd(){return s(this.days()/7)}
  function gd (line 344) | function gd(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}
  function hd (line 344) | function hd(a,b,c){var d=Nb(a).abs(),e=jf(d.as("s")),f=jf(d.as("m")),g=j...
  function id (line 346) | function id(a){return void 0===a?jf:"function"==typeof a&&(jf=a,!0)}
  function jd (line 348) | function jd(a,b){return void 0!==kf[a]&&(void 0===b?kf[a]:(kf[a]=b,!0))}
  function kd (line 348) | function kd(a){var b=this.localeData(),c=hd(this,!a,b);return a&&(c=b.pa...
  function ld (line 348) | function ld(){

FILE: web/vue/dist/vendor/toml.js
  function i (line 2) | function i(u,a){if(!t[u]){if(!r[u]){var c="function"==typeof require&&re...
  function e (line 2) | function e(e,r){function t(){this.constructor=e}t.prototype=r.prototype,...
  function r (line 2) | function r(e,r,t,n,i,o){this.message=e,this.expected=r,this.found=t,this...
  function t (line 2) | function t(e){function t(){return e.substring(Ot,Dt)}function n(e){throw...

FILE: web/vue/public/UIconfig.js
  constant CONFIG (line 7) | const CONFIG = {

FILE: web/vue/public/vendor/d3.js
  function n (line 2) | function n(t){return function(n,e){return Ms(t(n),e)}}
  function e (line 2) | function e(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.f...
  function r (line 2) | function r(t){return t.length}
  function i (line 2) | function i(){}
  function o (line 2) | function o(t,n){var e=new i;if(t instanceof i)t.each(function(t,n){e.set...
  function u (line 2) | function u(){return{}}
  function a (line 2) | function a(t,n,e){t[n]=e}
  function c (line 2) | function c(){return o()}
  function s (line 2) | function s(t,n,e){t.set(n,e)}
  function f (line 2) | function f(){}
  function l (line 2) | function l(t,n){var e=new f;if(t instanceof f)t.each(function(t){e.add(t...
  function h (line 2) | function h(t){return+t}
  function p (line 2) | function p(t){return t*t}
  function d (line 2) | function d(t){return t*(2-t)}
  function v (line 2) | function v(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}
  function _ (line 2) | function _(t){return t*t*t}
  function y (line 2) | function y(t){return--t*t*t+1}
  function g (line 2) | function g(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}
  function m (line 2) | function m(t){return 1-Math.cos(t*Tf)}
  function x (line 2) | function x(t){return Math.sin(t*Tf)}
  function b (line 2) | function b(t){return(1-Math.cos(Mf*t))/2}
  function w (line 2) | function w(t){return Math.pow(2,10*t-10)}
  function M (line 2) | function M(t){return 1-Math.pow(2,-10*t)}
  function T (line 2) | function T(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t)...
  function N (line 2) | function N(t){return 1-Math.sqrt(1-t*t)}
  function k (line 2) | function k(t){return Math.sqrt(1- --t*t)}
  function S (line 2) | function S(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+...
  function A (line 2) | function A(t){return 1-E(1-t)}
  function E (line 2) | function E(t){return(t=+t)<Nf?Lf*t*t:t<Sf?Lf*(t-=kf)*t+Af:t<Cf?Lf*(t-=Ef...
  function C (line 2) | function C(t){return((t*=2)<=1?1-E(1-t):E(t-1)+1)/2}
  function z (line 2) | function z(t,n){return t[0]-n[0]||t[1]-n[1]}
  function P (line 2) | function P(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&Wf(t...
  function q (line 2) | function q(){this._x0=this._y0=this._x1=this._y1=null,this._=[]}
  function L (line 2) | function L(){return new q}
  function R (line 2) | function R(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h...
  function U (line 2) | function U(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0...
  function D (line 2) | function D(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this}
  function O (line 2) | function O(t){return t[0]}
  function F (line 2) | function F(t){return t[1]}
  function I (line 2) | function I(t,n,e){var r=new Y(null==n?O:n,null==e?F:e,NaN,NaN,NaN,NaN);r...
  function Y (line 2) | function Y(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._...
  function B (line 2) | function B(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.dat...
  function j (line 2) | function j(t){if(!(t>=1))throw new Error;this._size=t,this._call=this._e...
  function H (line 2) | function H(t){if(!t._start)try{X(t)}catch(n){if(t._tasks[t._ended+t._act...
  function X (line 2) | function X(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._end...
  function V (line 2) | function V(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ende...
  function W (line 2) | function W(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t....
  function $ (line 2) | function $(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._ca...
  function Z (line 2) | function Z(t){return new j(arguments.length?+t:1/0)}
  function G (line 2) | function G(t){return t.innerRadius}
  function J (line 2) | function J(t){return t.outerRadius}
  function Q (line 2) | function Q(t){return t.startAngle}
  function K (line 2) | function K(t){return t.endAngle}
  function tt (line 2) | function tt(t){return t&&t.padAngle}
  function nt (line 2) | function nt(t){return t>=1?xl:t<=-1?-xl:Math.asin(t)}
  function et (line 2) | function et(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t...
  function rt (line 2) | function rt(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/Math.sqrt(a*a+c*c)...
  function it (line 2) | function it(t){this._context=t}
  function ot (line 2) | function ot(t){return t[0]}
  function ut (line 2) | function ut(t){return t[1]}
  function at (line 2) | function at(t){this._curve=t}
  function ct (line 2) | function ct(t){function n(n){return new at(t(n))}return n._curve=t,n}
  function st (line 2) | function st(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,...
  function ft (line 2) | function ft(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t...
  function lt (line 2) | function lt(t){this._context=t}
  function ht (line 2) | function ht(t){this._context=t}
  function pt (line 2) | function pt(t){this._context=t}
  function dt (line 2) | function dt(t,n){this._basis=new lt(t),this._beta=n}
  function vt (line 2) | function vt(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._...
  function _t (line 2) | function _t(t,n){this._context=t,this._k=(1-n)/6}
  function yt (line 2) | function yt(t,n){this._context=t,this._k=(1-n)/6}
  function gt (line 2) | function gt(t,n){this._context=t,this._k=(1-n)/6}
  function mt (line 2) | function mt(t,n,e){var r=t._x1,i=t._y1,o=t._x2,u=t._y2;if(t._l01_a>gl){v...
  function xt (line 2) | function xt(t,n){this._context=t,this._alpha=n}
  function bt (line 2) | function bt(t,n){this._context=t,this._alpha=n}
  function wt (line 2) | function wt(t,n){this._context=t,this._alpha=n}
  function Mt (line 2) | function Mt(t){this._context=t}
  function Tt (line 2) | function Tt(t){return t<0?-1:1}
  function Nt (line 2) | function Nt(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&...
  function kt (line 2) | function kt(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}
  function St (line 2) | function St(t,n,e){var r=t._x0,i=t._y0,o=t._x1,u=t._y1,a=(o-r)/3;t._cont...
  function At (line 2) | function At(t){this._context=t}
  function Et (line 2) | function Et(t){this._context=new Ct(t)}
  function Ct (line 2) | function Ct(t){this._context=t}
  function zt (line 2) | function zt(t){return new At(t)}
  function Pt (line 2) | function Pt(t){return new Et(t)}
  function qt (line 2) | function qt(t){this._context=t}
  function Lt (line 2) | function Lt(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),u=new ...
  function Rt (line 2) | function Rt(t,n){this._context=t,this._t=n}
  function Ut (line 2) | function Ut(t){return new Rt(t,0)}
  function Dt (line 2) | function Dt(t){return new Rt(t,1)}
  function Ot (line 2) | function Ot(t,n){return t[n]}
  function Ft (line 2) | function Ft(t){for(var n,e=0,r=-1,i=t.length;++r<i;)(n=+t[r][1])&&(e+=n)...
  function It (line 2) | function It(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[...
  function Yt (line 2) | function Yt(){}
  function Bt (line 2) | function Bt(t){var n;return t=(t+"").trim().toLowerCase(),(n=kh.exec(t))...
  function jt (line 2) | function jt(t){return new Wt(t>>16&255,t>>8&255,255&t,1)}
  function Ht (line 2) | function Ht(t,n,e,r){return r<=0&&(t=n=e=NaN),new Wt(t,n,e,r)}
  function Xt (line 2) | function Xt(t){return t instanceof Yt||(t=Bt(t)),t?(t=t.rgb(),new Wt(t.r...
  function Vt (line 2) | function Vt(t,n,e,r){return 1===arguments.length?Xt(t):new Wt(t,n,e,null...
  function Wt (line 2) | function Wt(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}
  function $t (line 2) | function $t(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=N...
  function Zt (line 2) | function Zt(t){if(t instanceof Jt)return new Jt(t.h,t.s,t.l,t.opacity);i...
  function Gt (line 2) | function Gt(t,n,e,r){return 1===arguments.length?Zt(t):new Jt(t,n,e,null...
  function Jt (line 2) | function Jt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}
  function Qt (line 2) | function Qt(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(...
  function Kt (line 2) | function Kt(t){if(t instanceof nn)return new nn(t.l,t.a,t.b,t.opacity);i...
  function tn (line 2) | function tn(t,n,e,r){return 1===arguments.length?Kt(t):new nn(t,n,e,null...
  function nn (line 2) | function nn(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}
  function en (line 2) | function en(t){return t>Hh?Math.pow(t,1/3):t/jh+Yh}
  function rn (line 2) | function rn(t){return t>Bh?t*t*t:jh*(t-Yh)}
  function on (line 2) | function on(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-....
  function un (line 2) | function un(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}
  function an (line 2) | function an(t){if(t instanceof sn)return new sn(t.h,t.c,t.l,t.opacity);t...
  function cn (line 2) | function cn(t,n,e,r){return 1===arguments.length?an(t):new sn(t,n,e,null...
  function sn (line 2) | function sn(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}
  function fn (line 2) | function fn(t){if(t instanceof hn)return new hn(t.h,t.s,t.l,t.opacity);t...
  function ln (line 2) | function ln(t,n,e,r){return 1===arguments.length?fn(t):new hn(t,n,e,null...
  function hn (line 2) | function hn(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}
  function pn (line 2) | function pn(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u...
  function dn (line 2) | function dn(t,n){return function(e){return t+e*n}}
  function vn (line 2) | function vn(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,functi...
  function _n (line 2) | function _n(t,n){var e=n-t;return e?dn(t,e>180||e<-180?e-360*Math.round(...
  function yn (line 2) | function yn(t){return 1===(t=+t)?gn:function(n,e){return e-n?vn(n,e,t):o...
  function gn (line 2) | function gn(t,n){var e=n-t;return e?dn(t,e):op(isNaN(t)?n:t)}
  function mn (line 2) | function mn(t){return function(n){var e,r,i=n.length,o=new Array(i),u=ne...
  function xn (line 2) | function xn(t){return function(){return t}}
  function bn (line 2) | function bn(t){return function(n){return t(n)+""}}
  function wn (line 2) | function wn(t){return"none"===t?mp:(Kh||(Kh=document.createElement("DIV"...
  function Mn (line 2) | function Mn(t){return null==t?mp:(ep||(ep=document.createElementNS("http...
  function Tn (line 2) | function Tn(t,n,e,r){function i(t){return t.length?t.pop()+" ":""}functi...
  function Nn (line 2) | function Nn(t){return((t=Math.exp(t))+1/t)/2}
  function kn (line 2) | function kn(t){return((t=Math.exp(t))-1/t)/2}
  function Sn (line 2) | function Sn(t){return((t=Math.exp(2*t))-1)/(t+1)}
  function An (line 2) | function An(t){return function(n,e){var r=t((n=Gt(n)).h,(e=Gt(e)).h),i=g...
  function En (line 2) | function En(t,n){var e=gn((t=tn(t)).l,(n=tn(n)).l),r=gn(t.a,n.a),i=gn(t....
  function Cn (line 2) | function Cn(t){return function(n,e){var r=t((n=cn(n)).h,(e=cn(e)).h),i=g...
  function zn (line 2) | function zn(t){return function n(e){function r(n,r){var i=t((n=ln(n)).h,...
  function Pn (line 2) | function Pn(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=argu...
  function qn (line 2) | function qn(t){this._=t}
  function Ln (line 2) | function Ln(t,n){return t.trim().split(/^|\s+/).map(function(t){var e=""...
  function Rn (line 2) | function Rn(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)r...
  function Un (line 2) | function Un(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]...
  function Dn (line 2) | function Dn(t){return new Function("d","return {"+t.map(function(t,n){re...
  function On (line 2) | function On(t,n){var e=Dn(t);return function(r,i){return n(e(r),i,t)}}
  function Fn (line 2) | function Fn(t){var n=Object.create(null),e=[];return t.forEach(function(...
  function In (line 2) | function In(t){return function(n,e){t(null==n?e:null)}}
  function Yn (line 2) | function Yn(t){var n=t.responseType;return n&&"text"!==n?t.response:t.re...
  function Bn (line 2) | function Bn(t,n){return function(e){return t(e.responseText,n)}}
  function jn (line 2) | function jn(){return sd||(hd(Hn),sd=ld.now()+fd)}
  function Hn (line 2) | function Hn(){sd=0}
  function Xn (line 2) | function Xn(){this._call=this._time=this._next=null}
  function Vn (line 2) | function Vn(t,n,e){var r=new Xn;return r.restart(t,n,e),r}
  function Wn (line 2) | function Wn(){jn(),++id;for(var t,n=Up;n;)(t=sd-n._time)>=0&&n._call.cal...
  function $n (line 2) | function $n(){sd=(cd=ld.now())+fd,id=od=0;try{Wn()}finally{id=0,Gn(),sd=0}}
  function Zn (line 2) | function Zn(){var t=ld.now(),n=t-cd;n>ad&&(fd-=n,cd=t)}
  function Gn (line 2) | function Gn(){for(var t,n,e=Up,r=1/0;e;)e._call?(r>e._time&&(r=e._time),...
  function Jn (line 2) | function Jn(t){if(!id){od&&(od=clearTimeout(od));var n=t-sd;n>24?(t<1/0&...
  function Qn (line 2) | function Qn(t,n,e,r){function i(n){return t(n=new Date(+n)),n}return i.f...
  function Kn (line 2) | function Kn(t){return Qn(function(n){n.setDate(n.getDate()-(n.getDay()+7...
  function te (line 2) | function te(t){return Qn(function(n){n.setUTCDate(n.getUTCDate()-(n.getU...
  function ne (line 2) | function ne(t){if(!(n=Av.exec(t)))throw new Error("invalid format: "+t);...
  function ee (line 2) | function ee(t){return t}
  function re (line 2) | function re(n){return Cv=Pv(n),t.format=Cv.format,t.formatPrefix=Cv.form...
  function ie (line 2) | function ie(t){if(0<=t.y&&t.y<100){var n=new Date(-1,t.m,t.d,t.H,t.M,t.S...
  function oe (line 2) | function oe(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t....
  function ue (line 2) | function ue(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}
  function ae (line 2) | function ae(t){function n(t,n){return function(e){var r,i,o,u=[],a=-1,c=...
  function ce (line 2) | function ce(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o...
  function se (line 2) | function se(t){return t.replace(Iv,"\\$&")}
  function fe (line 2) | function fe(t){return new RegExp("^(?:"+t.map(se).join("|")+")","i")}
  function le (line 2) | function le(t){for(var n={},e=-1,r=t.length;++e<r;)n[t[e].toLowerCase()]...
  function he (line 2) | function he(t,n,e){var r=Ov.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r...
  function pe (line 2) | function pe(t,n,e){var r=Ov.exec(n.slice(e));return r?(t.U=+r[0],e+r[0]....
  function de (line 2) | function de(t,n,e){var r=Ov.exec(n.slice(e));return r?(t.W=+r[0],e+r[0]....
  function ve (line 2) | function ve(t,n,e){var r=Ov.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r...
  function _e (line 2) | function _e(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r...
  function ye (line 2) | function ye(t,n,e){var r=/^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(n.slice(e,...
  function ge (line 2) | function ge(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+...
  function me (line 2) | function me(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r...
  function xe (line 2) | function xe(t,n,e){var r=Ov.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[...
  function be (line 2) | function be(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r...
  function we (line 2) | function we(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r...
  function Me (line 2) | function Me(t,n,e){var r=Ov.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r...
  function Te (line 2) | function Te(t,n,e){var r=Ov.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r...
  function Ne (line 2) | function Ne(t,n,e){var r=Fv.exec(n.slice(e,e+1));return r?e+r[0].length:-1}
  function ke (line 2) | function ke(t,n){return ce(t.getDate(),n,2)}
  function Se (line 2) | function Se(t,n){return ce(t.getHours(),n,2)}
  function Ae (line 2) | function Ae(t,n){return ce(t.getHours()%12||12,n,2)}
  function Ee (line 2) | function Ee(t,n){return ce(1+Cd.count($d(t),t),n,3)}
  function Ce (line 2) | function Ce(t,n){return ce(t.getMilliseconds(),n,3)}
  function ze (line 2) | function ze(t,n){return ce(t.getMonth()+1,n,2)}
  function Pe (line 2) | function Pe(t,n){return ce(t.getMinutes(),n,2)}
  function qe (line 2) | function qe(t,n){return ce(t.getSeconds(),n,2)}
  function Le (line 2) | function Le(t,n){return ce(Pd.count($d(t),t),n,2)}
  function Re (line 2) | function Re(t){return t.getDay()}
  function Ue (line 2) | function Ue(t,n){return ce(qd.count($d(t),t),n,2)}
  function De (line 2) | function De(t,n){return ce(t.getFullYear()%100,n,2)}
  function Oe (line 2) | function Oe(t,n){return ce(t.getFullYear()%1e4,n,4)}
  function Fe (line 2) | function Fe(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+c...
  function Ie (line 2) | function Ie(t,n){return ce(t.getUTCDate(),n,2)}
  function Ye (line 2) | function Ye(t,n){return ce(t.getUTCHours(),n,2)}
  function Be (line 2) | function Be(t,n){return ce(t.getUTCHours()%12||12,n,2)}
  function je (line 2) | function je(t,n){return ce(1+tv.count(gv(t),t),n,3)}
  function He (line 2) | function He(t,n){return ce(t.getUTCMilliseconds(),n,3)}
  function Xe (line 2) | function Xe(t,n){return ce(t.getUTCMonth()+1,n,2)}
  function Ve (line 2) | function Ve(t,n){return ce(t.getUTCMinutes(),n,2)}
  function We (line 2) | function We(t,n){return ce(t.getUTCSeconds(),n,2)}
  function $e (line 2) | function $e(t,n){return ce(ev.count(gv(t),t),n,2)}
  function Ze (line 2) | function Ze(t){return t.getUTCDay()}
  function Ge (line 2) | function Ge(t,n){return ce(rv.count(gv(t),t),n,2)}
  function Je (line 2) | function Je(t,n){return ce(t.getUTCFullYear()%100,n,2)}
  function Qe (line 2) | function Qe(t,n){return ce(t.getUTCFullYear()%1e4,n,4)}
  function Ke (line 2) | function Ke(){return"+0000"}
  function tr (line 2) | function tr(){return"%"}
  function nr (line 2) | function nr(n){return qv=ae(n),t.timeFormat=qv.format,t.timeParse=qv.par...
  function er (line 2) | function er(t){return t.toISOString()}
  function rr (line 2) | function rr(t){var n=new Date(t);return isNaN(n)?null:n}
  function ir (line 2) | function ir(t){function n(n){var o=n+"",u=e.get(o);if(!u){if(i!==Wv)retu...
  function or (line 2) | function or(){function t(){var t=i().length,r=u[1]<u[0],l=u[r-0],h=u[1-r...
  function ur (line 2) | function ur(t){var n=t.copy;return t.padding=t.paddingOuter,delete t.pad...
  function ar (line 2) | function ar(){return ur(or().paddingInner(1))}
  function cr (line 2) | function cr(t,n){return(n-=t=+t)?function(e){return(e-t)/n}:$v(n)}
  function sr (line 2) | function sr(t){return function(n,e){var r=t(n=+n,e=+e);return function(t...
  function fr (line 2) | function fr(t){return function(n,e){var r=t(n=+n,e=+e);return function(t...
  function lr (line 2) | function lr(t,n,e,r){var i=t[0],o=t[1],u=n[0],a=n[1];return o<i?(i=e(o,i...
  function hr (line 2) | function hr(t,n,e,r){var i=Math.min(t.length,n.length)-1,o=new Array(i),...
  function pr (line 2) | function pr(t,n){return n.domain(t.domain()).range(t.range()).interpolat...
  function dr (line 2) | function dr(t,n){function e(){return i=Math.min(a.length,c.length)>2?hr:...
  function vr (line 2) | function vr(t){var n=t.domain;return t.ticks=function(t){var e=n();retur...
  function _r (line 2) | function _r(){var t=dr(cr,lp);return t.copy=function(){return pr(t,_r())...
  function yr (line 2) | function yr(){function t(t){return+t}var n=[0,1];return t.invert=t,t.dom...
  function gr (line 2) | function gr(t,n){return(n=Math.log(n/t))?function(e){return Math.log(e/t...
  function mr (line 2) | function mr(t,n){return t<0?function(e){return-Math.pow(-n,e)*Math.pow(-...
  function xr (line 2) | function xr(t){return isFinite(t)?+("1e"+t):t<0?0:t}
  function br (line 2) | function br(t){return 10===t?xr:t===Math.E?Math.exp:function(n){return M...
  function wr (line 2) | function wr(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Mat...
  function Mr (line 2) | function Mr(t){return function(n){return-t(-n)}}
  function Tr (line 2) | function Tr(){function n(){return o=wr(i),u=br(i),r()[0]<0&&(o=Mr(o),u=M...
  function Nr (line 2) | function Nr(t,n){return t<0?-Math.pow(-t,n):Math.pow(t,n)}
  function kr (line 2) | function kr(){function t(t,n){return(n=Nr(n,e)-(t=Nr(t,e)))?function(r){...
  function Sr (line 2) | function Sr(){return kr().exponent(.5)}
  function Ar (line 2) | function Ar(){function t(){var t=0,o=Math.max(1,r.length);for(i=new Arra...
  function Er (line 2) | function Er(){function t(t){if(t<=t)return u[ks(o,t,0,i)]}function n(){v...
  function Cr (line 2) | function Cr(){function t(t){if(t<=t)return e[ks(n,t,0,r)]}var n=[.5],e=[...
  function zr (line 2) | function zr(t){return new Date(t);
  function Pr (line 3) | function Pr(t){return t instanceof Date?+t:+new Date(+t)}
  function qr (line 3) | function qr(t,n,r,i,o,u,a,c,s){function f(e){return(a(e)<e?v:u(e)<e?_:o(...
  function Lr (line 3) | function Lr(t){var n=t.length;return function(e){return t[Math.max(0,Mat...
  function Rr (line 3) | function Rr(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Mat...
  function Ur (line 3) | function Ur(t){return function(){var n=this.ownerDocument,e=this.namespa...
  function Dr (line 3) | function Dr(t){return function(){return this.ownerDocument.createElement...
  function Or (line 3) | function Or(){return new Fr}
  function Fr (line 3) | function Fr(){this._="@"+(++k_).toString(36)}
  function Ir (line 3) | function Ir(t,n,e){return t=Yr(t,n,e),function(n){var e=n.relatedTarget;...
  function Yr (line 3) | function Yr(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call...
  function Br (line 3) | function Br(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e...
  function jr (line 3) | function jr(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-...
  function Hr (line 3) | function Hr(t,n,e){var r=z_.hasOwnProperty(t.type)?Ir:Yr;return function...
  function Xr (line 3) | function Xr(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{r...
  function Vr (line 3) | function Vr(){}
  function Wr (line 3) | function Wr(){return[]}
  function $r (line 3) | function $r(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t....
  function Zr (line 3) | function Zr(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=...
  function Gr (line 3) | function Gr(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Ar...
  function Jr (line 3) | function Jr(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}
  function Qr (line 3) | function Qr(t){return function(){this.removeAttribute(t)}}
  function Kr (line 3) | function Kr(t){return function(){this.removeAttributeNS(t.space,t.local)}}
  function ti (line 3) | function ti(t,n){return function(){this.setAttribute(t,n)}}
  function ni (line 3) | function ni(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}
  function ei (line 3) | function ei(t,n){return function(){var e=n.apply(this,arguments);null==e...
  function ri (line 3) | function ri(t,n){return function(){var e=n.apply(this,arguments);null==e...
  function ii (line 3) | function ii(t){return function(){this.style.removeProperty(t)}}
  function oi (line 3) | function oi(t,n,e){return function(){this.style.setProperty(t,n,e)}}
  function ui (line 3) | function ui(t,n,e){return function(){var r=n.apply(this,arguments);null=...
  function ai (line 3) | function ai(t){return function(){delete this[t]}}
  function ci (line 3) | function ci(t,n){return function(){this[t]=n}}
  function si (line 3) | function si(t,n){return function(){var e=n.apply(this,arguments);null==e...
  function fi (line 3) | function fi(t){return t.trim().split(/^|\s+/)}
  function li (line 3) | function li(t){return t.classList||new hi(t)}
  function hi (line 3) | function hi(t){this._node=t,this._names=fi(t.getAttribute("class")||"")}
  function pi (line 3) | function pi(t,n){for(var e=li(t),r=-1,i=n.length;++r<i;)e.add(n[r])}
  function di (line 3) | function di(t,n){for(var e=li(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}
  function vi (line 3) | function vi(t){return function(){pi(this,t)}}
  function _i (line 3) | function _i(t){return function(){di(this,t)}}
  function yi (line 3) | function yi(t,n){return function(){(n.apply(this,arguments)?pi:di)(this,...
  function gi (line 3) | function gi(){this.textContent=""}
  function mi (line 3) | function mi(t){return function(){this.textContent=t}}
  function xi (line 3) | function xi(t){return function(){var n=t.apply(this,arguments);this.text...
  function bi (line 3) | function bi(){this.innerHTML=""}
  function wi (line 3) | function wi(t){return function(){this.innerHTML=t}}
  function Mi (line 3) | function Mi(t){return function(){var n=t.apply(this,arguments);this.inne...
  function Ti (line 3) | function Ti(){this.nextSibling&&this.parentNode.appendChild(this)}
  function Ni (line 3) | function Ni(){this.previousSibling&&this.parentNode.insertBefore(this,th...
  function ki (line 3) | function ki(){return null}
  function Si (line 3) | function Si(){var t=this.parentNode;t&&t.removeChild(this)}
  function Ai (line 3) | function Ai(t,n,e){var r=iy(t),i=r.CustomEvent;i?i=new i(n,e):(i=r.docum...
  function Ei (line 3) | function Ei(t,n){return function(){return Ai(this,t,n)}}
  function Ci (line 3) | function Ci(t,n){return function(){return Ai(this,t,n.apply(this,argumen...
  function zi (line 3) | function zi(t,n){this._groups=t,this._parents=n}
  function Pi (line 3) | function Pi(){return new zi([[document.documentElement]],yy)}
  function qi (line 3) | function qi(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>Ty)throw...
  function Li (line 3) | function Li(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>ky)throw...
  function Ri (line 3) | function Ri(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("...
  function Ui (line 3) | function Ui(t,n,e){function r(t){e.state=Ny,e.timer.restart(i,e.delay,e....
  function Di (line 3) | function Di(t,n){var e,r;return function(){var i=Li(this,t),o=i.tween;if...
  function Oi (line 3) | function Oi(t,n,e){var r,i;if("function"!=typeof e)throw new Error;retur...
  function Fi (line 3) | function Fi(t,n,e){var r=t._id;return t.each(function(){var t=Li(this,r)...
  function Ii (line 3) | function Ii(t){return function(){this.removeAttribute(t)}}
  function Yi (line 3) | function Yi(t){return function(){this.removeAttributeNS(t.space,t.local)}}
  function Bi (line 3) | function Bi(t,n,e){var r,i;return function(){var o=this.getAttribute(t);...
  function ji (line 3) | function ji(t,n,e){var r,i;return function(){var o=this.getAttributeNS(t...
  function Hi (line 3) | function Hi(t,n,e){var r,i,o;return function(){var u,a=e(this);return nu...
  function Xi (line 3) | function Xi(t,n,e){var r,i,o;return function(){var u,a=e(this);return nu...
  function Vi (line 3) | function Vi(t,n){function e(){var e=this,r=n.apply(e,arguments);return r...
  function Wi (line 3) | function Wi(t,n){function e(){var e=this,r=n.apply(e,arguments);return r...
  function $i (line 3) | function $i(t,n){return function(){qi(this,t).delay=+n.apply(this,argume...
  function Zi (line 3) | function Zi(t,n){return n=+n,function(){qi(this,t).delay=n}}
  function Gi (line 3) | function Gi(t,n){return function(){Li(this,t).duration=+n.apply(this,arg...
  function Ji (line 3) | function Ji(t,n){return n=+n,function(){Li(this,t).duration=n}}
  function Qi (line 3) | function Qi(t,n){if("function"!=typeof n)throw new Error;return function...
  function Ki (line 3) | function Ki(t){return(t+"").trim().split(/^|\s+/).every(function(t){var ...
  function to (line 3) | function to(t,n,e){var r,i,o=Ki(n)?qi:Li;return function(){var u=o(this,...
  function no (line 3) | function no(t){return function(){var n=this.parentNode;for(var e in this...
  function eo (line 3) | function eo(t,n){var e,r,i;return function(){var o=iy(this).getComputedS...
  function ro (line 3) | function ro(t){return function(){this.style.removeProperty(t)}}
  function io (line 3) | function io(t,n,e){var r,i;return function(){var o=iy(this).getComputedS...
  function oo (line 3) | function oo(t,n,e){var r,i,o;return function(){var u=iy(this).getCompute...
  function uo (line 3) | function uo(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return...
  function ao (line 3) | function ao(t){return function(){this.textContent=t}}
  function co (line 3) | function co(t){return function(){var n=t(this);this.textContent=null==n?...
  function so (line 3) | function so(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._i...
  function fo (line 3) | function fo(t){return Pi().transition(t)}
  function lo (line 3) | function lo(){return++Ky}
  function ho (line 3) | function ho(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.pare...
  function po (line 3) | function po(t,n,e){var r=t(e);return"translate("+(isFinite(r)?r:n(e))+",...
  function vo (line 3) | function vo(t,n,e){var r=t(e);return"translate(0,"+(isFinite(r)?r:n(e))+...
  function _o (line 3) | function _o(t){var n=t.bandwidth()/2;return t.round()&&(n=Math.round(n))...
  function yo (line 3) | function yo(){return!this.__axis}
  function go (line 3) | function go(t,n){function e(e){var s,f=null==i?n.ticks?n.ticks.apply(n,r...
  function mo (line 3) | function mo(t){return go(ag,t)}
  function xo (line 3) | function xo(t){return go(cg,t)}
  function bo (line 3) | function bo(t){return go(sg,t)}
  function wo (line 3) | function wo(t){return go(fg,t)}
  function Mo (line 3) | function Mo(t,n){return t.parent===n.parent?1:2}
  function To (line 3) | function To(t){return t.reduce(No,0)/t.length}
  function No (line 3) | function No(t,n){return t+n.x}
  function ko (line 3) | function ko(t){return 1+t.reduce(So,0)}
  function So (line 3) | function So(t,n){return Math.max(t,n.y)}
  function Ao (line 3) | function Ao(t){for(var n;n=t.children;)t=n[0];return t}
  function Eo (line 3) | function Eo(t){for(var n;n=t.children;)t=n[n.length-1];return t}
  function Co (line 3) | function Co(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i...
  function zo (line 3) | function zo(t,n){var e,r,i,o,u,a=new Uo(t),c=+t.value&&(a.value=t.value)...
  function Po (line 3) | function Po(){return zo(this).eachBefore(Lo)}
  function qo (line 3) | function qo(t){return t.children}
  function Lo (line 3) | function Lo(t){t.data=t.data.data}
  function Ro (line 3) | function Ro(t){var n=0;do t.height=n;while((t=t.parent)&&t.height<++n)}
  function Uo (line 3) | function Uo(t){this.data=t,this.depth=this.height=0,this.parent=null}
  function Do (line 3) | function Do(t){this._=t,this.next=null}
  function Oo (line 3) | function Oo(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r-n.r;return i*i+1e-6>e*e+r*r}
  function Fo (line 3) | function Fo(t,n){var e,r,i,o=null,u=t.head;switch(n.length){case 1:e=Io(...
  function Io (line 3) | function Io(t){return{x:t.x,y:t.y,r:t.r}}
  function Yo (line 3) | function Yo(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,f=a...
  function Bo (line 3) | function Bo(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,f=e.y,l...
  function jo (line 3) | function jo(t,n,e){var r=t.x,i=t.y,o=n.r+e.r,u=t.r+e.r,a=n.x-r,c=n.y-i,s...
  function Ho (line 3) | function Ho(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i>e*e+r*r}
  function Xo (line 3) | function Xo(t,n,e){var r=t.x-n,i=t.y-e;return r*r+i*i}
  function Vo (line 3) | function Vo(t){this._=t,this.next=null,this.previous=null}
  function Wo (line 3) | function Wo(t){if(!(i=t.length))return 0;var n,e,r,i;if(n=t[0],n.x=0,n.y...
  function $o (line 3) | function $o(t){return null==t?null:Zo(t)}
  function Zo (line 3) | function Zo(t){if("function"!=typeof t)throw new Error;return t}
  function Go (line 3) | function Go(){return 0}
  function Jo (line 3) | function Jo(t){return Math.sqrt(t.value)}
  function Qo (line 3) | function Qo(t){return function(n){n.children||(n.r=Math.max(0,+t(n)||0))}}
  function Ko (line 3) | function Ko(t,n){return function(e){if(r=e.children){var r,i,o,u=r.lengt...
  function tu (line 3) | function tu(t){return function(n){var e=n.parent;n.r*=t,e&&(n.x=e.x+t*n....
  function nu (line 3) | function nu(t){return t.id}
  function eu (line 3) | function eu(t){return t.parentId}
  function ru (line 3) | function ru(t,n){return t.parent===n.parent?1:2}
  function iu (line 3) | function iu(t){var n=t.children;return n?n[0]:t.t}
  function ou (line 3) | function ou(t){var n=t.children;return n?n[n.length-1]:t.t}
  function uu (line 3) | function uu(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}
  function au (line 3) | function au(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)n=i[o],...
  function cu (line 3) | function cu(t,n,e){return t.a.parent===n.parent?t.a:e}
  function su (line 3) | function su(t,n){this._=t,this.parent=null,this.children=null,this.A=nul...
  function fu (line 3) | function fu(t){for(var n,e,r,i,o,u=new su(t,0),a=[u];n=a.pop();)if(r=n._...
  function lu (line 3) | function lu(t,n,e,r,i,o){for(var u,a,c,s,f,l,h,p,d,v,_,y,g=[],m=n.childr...
  function hu (line 3) | function hu(t){return t.x+t.vx}
  function pu (line 3) | function pu(t){return t.y+t.vy}
  function du (line 3) | function du(t,n){return n}
  function vu (line 3) | function vu(t,n){var e=t.get(n);if(!e)throw new Error("missing: "+n);ret...
  function _u (line 3) | function _u(t){return t.x}
  function yu (line 3) | function yu(t){return t.y}
  function gu (line 3) | function gu(){t.event.stopImmediatePropagation()}
  function mu (line 3) | function mu(t,n){var e=t.document.documentElement,r=gy(t).on("dragstart....
  function xu (line 3) | function xu(t,n,e,r,i,o,u,a,c,s){this.target=t,this.type=n,this.subject=...
  function bu (line 3) | function bu(){return!t.event.button}
  function wu (line 3) | function wu(){return this.parentNode}
  function Mu (line 3) | function Mu(n){return null==n?{x:t.event.x,y:t.event.y}:n}
  function Tu (line 3) | function Tu(t){return t[0]}
  function Nu (line 3) | function Nu(t){return t[1]}
  function ku (line 3) | function ku(){this._=null}
  function Su (line 3) | function Su(t){t.U=t.C=t.L=t.R=t.P=t.N=null}
  function Au (line 3) | function Au(t,n){var e=n,r=n.R,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e...
  function Eu (line 3) | function Eu(t,n){var e=n,r=n.L,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e...
  function Cu (line 3) | function Cu(t){for(;t.L;)t=t.L;return t}
  function zu (line 3) | function zu(t,n,e,r){var i=[null,null],o=sm.push(i)-1;return i.left=t,i....
  function Pu (line 3) | function Pu(t,n,e){var r=[n,e];return r.left=t,r}
  function qu (line 3) | function qu(t,n,e,r){t[0]||t[1]?t.left===e?t[1]=r:t[0]=r:(t[0]=r,t.left=...
  function Lu (line 3) | function Lu(t,n,e,r,i){var o,u=t[0],a=t[1],c=u[0],s=u[1],f=a[0],l=a[1],h...
  function Ru (line 3) | function Ru(t,n,e,r,i){var o=t[1];if(o)return!0;var u,a,c=t[0],s=t.left,...
  function Uu (line 3) | function Uu(t,n,e,r){for(var i,o=sm.length;o--;)Ru(i=sm[o],t,n,e,r)&&Lu(...
  function Du (line 3) | function Du(t){return am[t.index]={site:t,halfedges:[]}}
  function Ou (line 3) | function Ou(t,n){var e=t.site,r=n.left,i=n.right;return e===i&&(i=r,r=e)...
  function Fu (line 3) | function Fu(t,n){return n[+(n.left!==t.site)]}
  function Iu (line 3) | function Iu(t,n){return n[+(n.left===t.site)]}
  function Yu (line 3) | function Yu(){for(var t,n,e,r,i=0,o=am.length;i<o;++i)if((t=am[i])&&(r=(...
  function Bu (line 3) | function Bu(t,n,e,r){var i,o,u,a,c,s,f,l,h,p,d,v,_=am.length,y=!0;for(i=...
  function ju (line 3) | function ju(){Su(this),this.x=this.y=this.arc=this.site=this.cy=null}
  function Hu (line 3) | function Hu(t){var n=t.P,e=t.N;if(n&&e){var r=n.site,i=t.site,o=e.site;i...
  function Xu (line 3) | function Xu(t){var n=t.circle;n&&(n.P||(om=n.N),cm.remove(n),fm.push(n),...
  function Vu (line 3) | function Vu(){Su(this),this.edge=this.site=this.circle=null}
  function Wu (line 3) | function Wu(t){var n=lm.pop()||new Vu;return n.site=t,n}
  function $u (line 3) | function $u(t){Xu(t),um.remove(t),lm.push(t),Su(t)}
  function Zu (line 3) | function Zu(t){var n=t.circle,e=n.x,r=n.cy,i=[e,r],o=t.P,u=t.N,a=[t];$u(...
  function Gu (line 3) | function Gu(t){for(var n,e,r,i,o=t[0],u=t[1],a=um._;a;)if(r=Ju(a,
Condensed preview — 371 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,307K chars).
[
  {
    "path": ".dockerignore",
    "chars": 75,
    "preview": "node_modules\n.travis.yml\nvolumes\nconfig.js\nsample-config.js\n.git\n.gitignore"
  },
  {
    "path": ".editorconfig",
    "chars": 147,
    "preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 618,
    "preview": "**Note: this is the technical bug tracker, please use other platforms for getting support and starting a (non technical)"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 261,
    "preview": "* **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)\n\n\n\n* **What is the current behavi"
  },
  {
    "path": ".github/stale.yml",
    "chars": 832,
    "preview": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 60\n# Number of days of inactivity before a "
  },
  {
    "path": ".gitignore",
    "chars": 551,
    "preview": "# Numerous always-ignore extensions\n*.diff\n*.err\n*.orig\n*.log\n*.rej\n*.swo\n*.swp\n*.vi\n*~\n*.sass-cache\n\n# OS or Editor fol"
  },
  {
    "path": ".prettierrc",
    "chars": 51,
    "preview": "{\n  \"trailingComma\": \"es5\",\n  \"singleQuote\": true\n}"
  },
  {
    "path": ".travis.yml",
    "chars": 39,
    "preview": "language: node_js\nnode_js:\n  - \"8.11.2\""
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2532,
    "preview": "# Contributing\n\nThanks for (thinking about) contributing to Gekko, all help is wanted!\n\n## Before Submitting an Issue\n\nF"
  },
  {
    "path": "Dockerfile",
    "chars": 808,
    "preview": "FROM node:8\n\nENV HOST localhost\nENV PORT 3000\n\n# Create app directory\nRUN mkdir -p /usr/src/app\nWORKDIR /usr/src/app\n\n# "
  },
  {
    "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": 1802,
    "preview": "# This repo is not maintained anymore\n\nI am officially not maintaining this project anymore. It was an amazing journey a"
  },
  {
    "path": "appveyor.yml",
    "chars": 240,
    "preview": "init:\n  - git config --global core.autocrlf input\n\nenvironment:\n  nodejs_version: \"9\"\n\ninstall:\n  - ps: Install-Product "
  },
  {
    "path": "config/adapters/mongodb.toml",
    "chars": 138,
    "preview": "connectionString = \"mongodb://mongodb/gekko\"\npath = \"plugins/mongodb\"\nversion = 0.1\n\n[[dependencies]]\nmodule = \"mongojs\""
  },
  {
    "path": "config/adapters/postgresql.toml",
    "chars": 148,
    "preview": "connectionString = \"postgres://user:pass@localhost:5432\"\npath = \"plugins/postgresql\"\nversion = 0.1\n\n[[dependencies]]\nmod"
  },
  {
    "path": "config/adapters/sqlite.toml",
    "chars": 118,
    "preview": "dataDirectory = \"history\"\npath = \"plugins/sqlite\"\nversion = 0.1\n\n[[dependencies]]\nmodule = \"sqlite3\"\nversion = \"3.1.4\""
  },
  {
    "path": "config/backtest.toml",
    "chars": 147,
    "preview": "batchSize = 50\n\n# scan for available dateranges\ndaterange = \"scan\"\n# or specify it like so:\n# [daterange]\n# from = \"2015"
  },
  {
    "path": "config/general.toml",
    "chars": 131,
    "preview": "debug = true\n\n# what database should Gekko use?\nadapter = 'sqlite'\n\n[watch]\nexchange = 'Poloniex'\ncurrency = 'USDT'\nasse"
  },
  {
    "path": "config/plugins/candleWriter.toml",
    "chars": 33,
    "preview": "enabled = true\nadapter = \"sqlite\""
  },
  {
    "path": "config/plugins/paperTrader.toml",
    "chars": 113,
    "preview": "feeMaker = 0.25\nfeeTaker = 0.25\nfeeUsing = 'maker'\nslippage = 0.05\n\n[simulationBalance]\nasset = 1\ncurrency = 100\n"
  },
  {
    "path": "config/plugins/performanceAnalyzer.toml",
    "chars": 129,
    "preview": "# Used to calculate sharpe ratio\n# yearly % of riskfree return for example\n# treasury bonds or bank interest.\n\nriskFreeR"
  },
  {
    "path": "config/plugins/pushbullet.toml",
    "chars": 322,
    "preview": "enabled = false\n\n# Send 'Gekko starting' message if true\nsendMessageOnStart = true\n\n# disable advice printout if it's so"
  },
  {
    "path": "config/plugins/trader.toml",
    "chars": 178,
    "preview": "enabled = false\n\n## NOTE: once you filled in the following\n## never share this file with anyone!\n\nkey = \"\"\nsecret = \"\"\n#"
  },
  {
    "path": "config/plugins/tradingAdvisor.toml",
    "chars": 107,
    "preview": "enabled = true\n\ncandleSize = 60\nhistorySize = 25\nmethod = \"MACD\"\n\n[talib]\nenabled = false\nversion = \"1.0.2\""
  },
  {
    "path": "config/strategies/CCI.toml",
    "chars": 183,
    "preview": "# constant multiplier. 0.015 gets to around 70% fit\nconstant = 0.015\n\n# history size, make same or smaller than history\n"
  },
  {
    "path": "config/strategies/DEMA.toml",
    "chars": 51,
    "preview": "weight = 21\n\n[thresholds]\ndown = -0.025\nup = 0.025\n"
  },
  {
    "path": "config/strategies/MACD.toml",
    "chars": 86,
    "preview": "short = 10\nlong = 21\nsignal = 9\n\n[thresholds]\ndown = -0.025\nup = 0.025\npersistence = 1"
  },
  {
    "path": "config/strategies/PPO.toml",
    "chars": 86,
    "preview": "short = 12\nlong = 26\nsignal = 9\n\n[thresholds]\ndown = -0.025\nup = 0.025\npersistence = 2"
  },
  {
    "path": "config/strategies/RSI.toml",
    "chars": 62,
    "preview": "interval = 14\n\n[thresholds]\nlow = 30\nhigh = 70\npersistence = 1"
  },
  {
    "path": "config/strategies/StochRSI.toml",
    "chars": 61,
    "preview": "interval = 3\n\n[thresholds]\nlow = 20\nhigh = 80\npersistence = 3"
  },
  {
    "path": "config/strategies/TMA.toml",
    "chars": 32,
    "preview": "short = 7\nmedium = 25\nlong = 99\n"
  },
  {
    "path": "config/strategies/TSI.toml",
    "chars": 70,
    "preview": "short = 13\nlong = 25\n\n[thresholds]\nlow = -25\nhigh = 25\npersistence = 1"
  },
  {
    "path": "config/strategies/UO.toml",
    "chars": 144,
    "preview": "[first]\nweight = 4\nperiod = 7\n\n[second]\nweight = 2\nperiod = 14\n\n[third]\nweight = 1\nperiod = 28\n\n[thresholds]\nlow = 30\nhi"
  },
  {
    "path": "config/strategies/custom.toml",
    "chars": 22,
    "preview": "my_custom_setting = 10"
  },
  {
    "path": "config/strategies/talib-macd.toml",
    "chars": 115,
    "preview": "[parameters]\noptInFastPeriod = 10\noptInSlowPeriod = 21\noptInSignalPeriod = 9\n\n[thresholds]\ndown = -0.025\nup = 0.025"
  },
  {
    "path": "config/strategies/tulip-adx.toml",
    "chars": 85,
    "preview": "historySize = 80\noptInTimePeriod = 15\ncandleSize = 10\n\n[thresholds]\nup = 30\ndown = 20"
  },
  {
    "path": "config/strategies/tulip-macd.toml",
    "chars": 115,
    "preview": "[parameters]\noptInFastPeriod = 10\noptInSlowPeriod = 21\noptInSignalPeriod = 9\n\n[thresholds]\ndown = -0.025\nup = 0.025"
  },
  {
    "path": "config/strategies/tulip-multi-strat.toml",
    "chars": 215,
    "preview": "optInTimePeriod = 2\noptInFastPeriod = 4\noptInSlowPeriod = 7\noptInSignalPeriod = 23.707189677282354\n\ncandleSize = 1\nhisto"
  },
  {
    "path": "config/strategies/varPPO.toml",
    "chars": 179,
    "preview": "momentum = \"TSI\" # RSI, TSI or UO\n\n[thresholds]\nweightLow = 120\nweightHigh = -120\n\n# How many candle intervals should a "
  },
  {
    "path": "core/budfox/budfox.js",
    "chars": 1826,
    "preview": "// Budfox is the realtime market for Gekko!\n//\n// Read more here:\n// @link https://github.com/askmike/gekko/blob/stable/"
  },
  {
    "path": "core/budfox/candleCreator.js",
    "chars": 4648,
    "preview": "// The CandleCreator creates one minute candles based on trade batches. Note\n// that it also adds empty candles to fill "
  },
  {
    "path": "core/budfox/candleManager.js",
    "chars": 834,
    "preview": "// The candleManager consumes trades and emits:\n// - `candles`: array of minutly candles.\n// - `candle`: the most recent"
  },
  {
    "path": "core/budfox/heart.js",
    "chars": 1172,
    "preview": "// The heart schedules and emit ticks every 20 seconds.\n\nvar util = require(__dirname + '/../util');\nvar log = require(u"
  },
  {
    "path": "core/budfox/marketDataProvider.js",
    "chars": 996,
    "preview": "// \n// The market data provider will fetch data from a datasource on tick. It emits:\n// \n// - `trades`: batch of newly d"
  },
  {
    "path": "core/budfox/marketFetcher.js",
    "chars": 3070,
    "preview": "//\n// The fetcher is responsible for fetching new\n// market data at the exchange on interval. It will emit\n// the follow"
  },
  {
    "path": "core/budfox/tradeBatcher.js",
    "chars": 2756,
    "preview": "// \n// Small wrapper that only propagates new trades.\n// \n// Expects trade batches to be written like:\n// [\n//  {\n//    "
  },
  {
    "path": "core/candleBatcher.js",
    "chars": 2075,
    "preview": "// internally we only use 1m\n// candles, this can easily\n// convert them to any desired\n// size.\n\n// Acts as ~fake~ stre"
  },
  {
    "path": "core/emitter.js",
    "chars": 968,
    "preview": "// Gekko uses a custom event emitter within the GekkoStream (the plugins) to guarantee\n// the correct order of events th"
  },
  {
    "path": "core/gekkoStream.js",
    "chars": 3121,
    "preview": "// Small writable stream wrapper that\n// passes data to all `candleConsumers`.\n\nconst Writable = require('stream').Writa"
  },
  {
    "path": "core/log.js",
    "chars": 1773,
    "preview": "/*\n\n  Lightweight logger, print everything that is send to error, warn\n  and messages to stdout (the terminal). If confi"
  },
  {
    "path": "core/markets/backtest.js",
    "chars": 2608,
    "preview": "var _ = require('lodash');\nvar util = require('../util');\nvar config = util.getConfig();\nvar dirs = util.dirs();\nvar log"
  },
  {
    "path": "core/markets/importer.js",
    "chars": 2513,
    "preview": "var _ = require('lodash');\nvar util = require('../util');\nvar config = util.getConfig();\nvar dirs = util.dirs();\nvar log"
  },
  {
    "path": "core/markets/leech.js",
    "chars": 2084,
    "preview": "// a leech market is \"semi-realtime\" and pulls out candles of a\n// database (which is expected to be updated regularly, "
  },
  {
    "path": "core/markets/realtime.js",
    "chars": 514,
    "preview": "const _ = require('lodash');\n\nconst util = require('../util');\nconst dirs = util.dirs();\n\nconst exchangeChecker = requir"
  },
  {
    "path": "core/pipeline.js",
    "chars": 6299,
    "preview": "/*\n\n  A pipeline implements a full Gekko Flow based on a config and \n  a mode. The mode is an abstraction that tells Gek"
  },
  {
    "path": "core/pluginUtil.js",
    "chars": 2838,
    "preview": "var _ = require('lodash');\nvar async = require('async');\nvar Emitter = require('./emitter');\n\nvar util = require(__dirna"
  },
  {
    "path": "core/prepareDateRange.js",
    "chars": 1843,
    "preview": "var _ = require('lodash');\nvar prompt = require('prompt-lite');\nvar moment = require('moment');\n\nvar util = require('./u"
  },
  {
    "path": "core/stats.js",
    "chars": 395,
    "preview": "const stats = require('stats-lite');\nconst lodash = require('lodash');\n\n\n// simply monkey patch the stats with other stu"
  },
  {
    "path": "core/talib.js",
    "chars": 61483,
    "preview": "var semver = require(\"semver\");\nvar _ = require('lodash');\n\n// validate that talib is installed, if not we'll throw an e"
  },
  {
    "path": "core/tools/candleLoader.js",
    "chars": 2017,
    "preview": "// TODO: properly handle a daterange for which no data is available.\n\nconst batchSize = 1000;\n\nconst _ = require('lodash"
  },
  {
    "path": "core/tools/configBuilder.js",
    "chars": 1243,
    "preview": "const fs = require('fs');\nconst _ = require('lodash');\nconst toml = require('toml');\n\nconst util = require('../util');\nc"
  },
  {
    "path": "core/tools/dataStitcher.js",
    "chars": 7492,
    "preview": "var _ = require('lodash');\nvar fs = require('fs');\nvar moment = require('moment');\n\nvar util = require('../util');\nvar c"
  },
  {
    "path": "core/tools/dateRangeScanner.js",
    "chars": 3495,
    "preview": "var BATCH_SIZE = 60; // minutes\nvar MISSING_CANDLES_ALLOWED = 3; // minutes, per batch\n\nvar _ = require('lodash');\nvar m"
  },
  {
    "path": "core/tulind.js",
    "chars": 26504,
    "preview": "var semver = require(\"semver\");\nvar _ = require('lodash');\n\n// validate that talib is installed, if not we'll throw an e"
  },
  {
    "path": "core/util.js",
    "chars": 4491,
    "preview": "var moment = require('moment');\nvar _ = require('lodash');\nvar path = require('path');\nvar fs = require('fs');\nvar semve"
  },
  {
    "path": "core/workers/datasetScan/parent.js",
    "chars": 1148,
    "preview": "var _ = require('lodash');\nvar moment = require('moment');\nvar async = require('async');\nvar os = require('os');\n\nvar ut"
  },
  {
    "path": "core/workers/dateRangeScan/child.js",
    "chars": 500,
    "preview": "var util = require(__dirname + '/../../util');\n\nvar dirs = util.dirs();\nvar ipc = require('relieve').IPCEE(process);\n\nip"
  },
  {
    "path": "core/workers/dateRangeScan/parent.js",
    "chars": 510,
    "preview": "var ForkTask = require('relieve').tasks.ForkTask;\nvar fork = require('child_process').fork;\n\nmodule.exports = function(c"
  },
  {
    "path": "core/workers/loadCandles/child.js",
    "chars": 587,
    "preview": "var start = (config, candleSize, daterange) => {\n  var util = require(__dirname + '/../../util');\n\n  // force correct ge"
  },
  {
    "path": "core/workers/loadCandles/parent.js",
    "chars": 1317,
    "preview": "// example usage:\n\n// let config = {\n//   watch: {\n//     exchange: 'poloniex',\n//     currency: 'USDT',\n//     asset: '"
  },
  {
    "path": "core/workers/pipeline/child.js",
    "chars": 1638,
    "preview": "/*\n\n  Gekko is a Bitcoin trading bot for popular Bitcoin exchanges written \n  in node, it features multiple trading meth"
  },
  {
    "path": "core/workers/pipeline/messageHandlers/backtestHandler.js",
    "chars": 505,
    "preview": "// Relay the backtest message it when it comes in.\n\nmodule.exports = done => {\n  let backtest;\n\n  return {\n    message: "
  },
  {
    "path": "core/workers/pipeline/messageHandlers/importerHandler.js",
    "chars": 499,
    "preview": "module.exports = cb => {\n\n  return {\n    message: message => {\n\n      if(message.event === 'marketUpdate')\n        cb(nu"
  },
  {
    "path": "core/workers/pipeline/messageHandlers/realtimeHandler.js",
    "chars": 388,
    "preview": "// pass back all messages as is\n// (except for errors and logs)\n\nmodule.exports = cb => {\n\n  return {\n    message: messa"
  },
  {
    "path": "core/workers/pipeline/parent.js",
    "chars": 717,
    "preview": "var fork = require('child_process').fork;\n\nmodule.exports = (mode, config, callback) => {\n  var debug = typeof v8debug ="
  },
  {
    "path": "docker-compose.yml",
    "chars": 1131,
    "preview": "version: '3'\nservices:\n  gekko:\n    build: ./\n    volumes:\n      - ./volumes/gekko/history:/usr/src/app/history\n      - "
  },
  {
    "path": "docker-entrypoint.sh",
    "chars": 358,
    "preview": "#!/bin/bash\n\nsed -i 's/127.0.0.1/0.0.0.0/g' /usr/src/app/web/vue/dist/UIconfig.js\nsed -i 's/localhost/'${HOST}'/g' /usr/"
  },
  {
    "path": "docs/commandline/Importing.md",
    "chars": 2011,
    "preview": "# Importing\n\n*Note: this documentation was written for running Gekko via the command line. If you are using the UI you c"
  },
  {
    "path": "docs/commandline/about_the_commandline.md",
    "chars": 1201,
    "preview": "# About the commandline\n\nYou don't have to use the UI to control Gekko, you can also use the commandline if you don't ha"
  },
  {
    "path": "docs/commandline/backtesting.md",
    "chars": 4513,
    "preview": "# Backtesting with Gekko\n\n*Note: this documentation was written for running Gekko via the command line. If you are using"
  },
  {
    "path": "docs/commandline/plugins.md",
    "chars": 9225,
    "preview": "## Enabling plugins\n\n*Note: this documentation was written for running Gekko via the command line. If you are using the "
  },
  {
    "path": "docs/commandline/tradebot.md",
    "chars": 1032,
    "preview": "# Tradebot\n\nYou can set Gekko up as a tradebot, this will instruct Gekko to:\n\n- Watch a live market.\n- Run a strategy (i"
  },
  {
    "path": "docs/extending/add_a_plugin.md",
    "chars": 1701,
    "preview": "# Plugins\n\nA plugin is a low level module or plugin that can act upon events bubbling\nthrough Gekko. If you want to have"
  },
  {
    "path": "docs/extending/add_an_exchange.md",
    "chars": 11409,
    "preview": "# Exchanges\n\n*This is a technical document about adding a new exchange to Gekko and Gekko Broker.*\n\nGekko arranges all c"
  },
  {
    "path": "docs/extending/other_software.md",
    "chars": 1056,
    "preview": "# Other Software\n\nSince Gekko version 0.4 Gekko can launch a process which exposes a web (REST and Websocket) API that c"
  },
  {
    "path": "docs/features/backtesting.md",
    "chars": 2645,
    "preview": "# Backtesting\n\nGekko supports backtesting strategies over historical data. A Backtest is a simulation where you simulate"
  },
  {
    "path": "docs/features/importing.md",
    "chars": 964,
    "preview": "# Importing\n\nIn order to [backtest](./backtesting.md) your strategies you will need to have historical market data to te"
  },
  {
    "path": "docs/features/paper_trading.md",
    "chars": 757,
    "preview": "# Paper trading\n\nGekko can automatically run a strategy over the live markets and simulate in realtime what happen if yo"
  },
  {
    "path": "docs/features/trading_bot.md",
    "chars": 1655,
    "preview": "# Trading bot\n\nOnce you have run enough simulations (using [backtesting](./backtesting.md) and [paper trading](./paper_t"
  },
  {
    "path": "docs/gekko-broker/introduction.md",
    "chars": 4107,
    "preview": "# Gekko Broker\n\nOrder execution library for bitcoin and crypto exchanges. This library is Gekko's execution engine for a"
  },
  {
    "path": "docs/gekko-broker/sticky_order.md",
    "chars": 1333,
    "preview": "# Sticky Order\n\nAn advanced order that stays at the top of the book (until the optional limit). The order will automatic"
  },
  {
    "path": "docs/gekko-broker/wrapper_api.md",
    "chars": 1699,
    "preview": "# Wrapper API\n\nGekko Broker is a library that sits between trading applications and Gekko Broker Exchange Wrappers. Whic"
  },
  {
    "path": "docs/installation/configuring_gekko_on_a_server.md",
    "chars": 5928,
    "preview": "# Configuring Gekko on a server\n\n*NOTE: unfortunately configuring Gekko to run on a server is hard. Unless you are runni"
  },
  {
    "path": "docs/installation/installing_gekko.md",
    "chars": 2797,
    "preview": "# Installing Gekko\n\n*NOTE: unfortunately installing and managing Gekko is hard. You will need to touch the commandline a"
  },
  {
    "path": "docs/installation/installing_gekko_on_raspberry_pi_2_or_3.md",
    "chars": 2174,
    "preview": "# Installing Gekko on Raspberry Pi 2 or 3\n\nThis manual is intended for a Raspberry Pi 2 or 3 with freshly installed Rasp"
  },
  {
    "path": "docs/installation/installing_gekko_on_windows.md",
    "chars": 2847,
    "preview": "# Installing Gekko on windows\n\n*NOTE: unfortunately installing and managing Gekko is hard. You will need to touch the co"
  },
  {
    "path": "docs/installation/installing_gekko_on_windows_with_bash_on_windows_10.md",
    "chars": 3855,
    "preview": "# Installing Gekko on Windows with bash on Windows 10\n\n*NOTE: unfortunately installing and managing Gekko is hard. You w"
  },
  {
    "path": "docs/installation/installing_gekko_using_docker.md",
    "chars": 879,
    "preview": "# Installing Gekko using Docker\n\nInstalling and running gekko in a docker container for use on the same machine is simpl"
  },
  {
    "path": "docs/installation/updating_gekko.md",
    "chars": 1888,
    "preview": "# Updating Gekko\n\n## Prepare\n\nBefore updating your local version of Gekko it's good to keep a few things in mind:\n\n- If "
  },
  {
    "path": "docs/internals/architecture.md",
    "chars": 3819,
    "preview": "# Gekko's architecture\n\n![Gekko architecture](https://wizb.it/gekko/static/architecture.jpg)\n\nEvery Gekko instance has t"
  },
  {
    "path": "docs/internals/budfox.md",
    "chars": 3161,
    "preview": "# BudFox\n\n**Similar to the [movie Wallstreet](https://en.wikipedia.org/wiki/Wall_Street_(1987_film)), Gekko delegates th"
  },
  {
    "path": "docs/internals/events.md",
    "chars": 16183,
    "preview": "# Events\n\nAs described in the [architecture](./architecture.md) events play a key role in the complete system: they rela"
  },
  {
    "path": "docs/internals/gekko_ui.md",
    "chars": 2656,
    "preview": "# Gekko UI\n\nWhen you launch Gekko UI, you start a basic nodejs webserver with 3 components:\n\n- It will serve frontend (H"
  },
  {
    "path": "docs/internals/plugins.md",
    "chars": 2306,
    "preview": "# Plugins\n\n*This is a technical document explaining the role of Plugins in the Gekko codebase. For a non technical docum"
  },
  {
    "path": "docs/internals/server_api.md",
    "chars": 15829,
    "preview": "# Server API\n\nThe Gekko project has three major components:\n\n - [Actual Gekko instance](./architecture.md)\n - A nodejs s"
  },
  {
    "path": "docs/introduction/about_gekko.md",
    "chars": 4581,
    "preview": "# About Gekko\n\nGekko is a **free and open source** Bitcoin TA trading and backtesting platform that connects to popular "
  },
  {
    "path": "docs/introduction/getting_help.md",
    "chars": 1371,
    "preview": "# Getting Help\n\nAre you getting stuck installing or using Gekko? Are you struggling with understanding Gekko? Running in"
  },
  {
    "path": "docs/introduction/roadmap.md",
    "chars": 421,
    "preview": "# Roadmap\n\nGekko is ever evolving and we are constantly working on new features and upgrades!\n\nThis is a small selection"
  },
  {
    "path": "docs/introduction/scope.md",
    "chars": 2757,
    "preview": "# Scope\n\nGekko is a free and open source tool that is designed as a starters kit for automated trading on cryptocurrency"
  },
  {
    "path": "docs/introduction/supported_exchanges.md",
    "chars": 4117,
    "preview": "## Supported exchanges\n\nGekko is able to directly communicate with the APIs of a number of exchanges. However communicat"
  },
  {
    "path": "docs/introduction/supporting_the_project.md",
    "chars": 470,
    "preview": "# Supporting the project\n\nGekko is free and open source software. We don't make any money by publishing it, keeping it u"
  },
  {
    "path": "docs/strategies/creating_a_strategy.md",
    "chars": 8429,
    "preview": "# Creating a strategy\n\n*Have you made your own strategy? Gekko Plus is hosting an official Strategy contest: submit your"
  },
  {
    "path": "docs/strategies/gekko_indicators.md",
    "chars": 5017,
    "preview": "# Gekko indicators\n\nWhen [creating your own strategy](./creating_a_strategy.md) there are a few built in indicators you "
  },
  {
    "path": "docs/strategies/introduction.md",
    "chars": 9492,
    "preview": "# Gekko Strategies\n\nGekko uses [technical analysis indicators](http://www.investopedia.com/articles/active-trading/10291"
  },
  {
    "path": "docs/strategies/talib_indicators.md",
    "chars": 7728,
    "preview": "# TA-lib indicators\n\nWhen writing [your own strategy](./creating_a_strategy.md) you can use all indicators offered by [t"
  },
  {
    "path": "docs/strategies/tulip_indicators.md",
    "chars": 21474,
    "preview": "# Tulip indicators\n\nWhen writing [your own strategy](./creating_a_trading_method.md) you can use all indicators offered "
  },
  {
    "path": "exchange/.npmignore",
    "chars": 7,
    "preview": "nusadua"
  },
  {
    "path": "exchange/README.md",
    "chars": 90,
    "preview": "# Gekko Broker\n\nsee [the docs](https://gekko.wizb.it/docs/gekko-broker/introduction.html)."
  },
  {
    "path": "exchange/dependencyCheck.js",
    "chars": 554,
    "preview": "const deps = require('./package.json').dependencies;\n\nconst missing = [];\n\nObject.keys(deps).forEach(dep => {\n  try {\n  "
  },
  {
    "path": "exchange/exchangeChecker.js",
    "chars": 3283,
    "preview": "const _ = require('lodash');\nconst fs = require('fs');\nconst moment = require('moment');\nconst errors = require('./excha"
  },
  {
    "path": "exchange/exchangeErrors.js",
    "chars": 814,
    "preview": "const _ = require('lodash');\n\nconst ExchangeError = function(message) {\n  _.bindAll(this);\n\n  this.name = \"ExchangeError"
  },
  {
    "path": "exchange/exchangeUtils.js",
    "chars": 3587,
    "preview": "// generic low level reusuable utils for interacting with exchanges.\n\nconst retry = require('retry');\nconst errors = req"
  },
  {
    "path": "exchange/gekkoBroker.js",
    "chars": 4216,
    "preview": "/*\n  The broker manages all communicatinn with the exchange, delegating:\n\n  - the management of the portfolio to the por"
  },
  {
    "path": "exchange/orders/index.js",
    "chars": 66,
    "preview": "const sticky = require('./sticky');\n\nmodule.exports = {\n  sticky\n}"
  },
  {
    "path": "exchange/orders/limit.js",
    "chars": 5040,
    "preview": "// NOTE: this is currently broken, see\n// @link https://github.com/askmike/gekko/issues/2398\n\nthrow ':(';\n\n/*\n  The limi"
  },
  {
    "path": "exchange/orders/order.js",
    "chars": 1763,
    "preview": "const EventEmitter = require('events');\nconst _ = require('lodash');\n\nconst exchangeUtils = require('../exchangeUtils');"
  },
  {
    "path": "exchange/orders/states.js",
    "chars": 614,
    "preview": "const states = {\n  // Not created\n  INITIALIZING: 'INITIALIZING',\n\n  // Created and send to the exchange, but no acknowl"
  },
  {
    "path": "exchange/orders/sticky.js",
    "chars": 18300,
    "preview": "/*\n  The sticky order is an advanced order:\n    - It is created at a limit price of X\n      - if limit is not specified "
  },
  {
    "path": "exchange/package.json",
    "chars": 1014,
    "preview": "{\n  \"name\": \"gekko-broker\",\n  \"version\": \"0.6.8\",\n  \"description\": \"Gekko's order execution library for bitcoin & crypto"
  },
  {
    "path": "exchange/portfolioManager.js",
    "chars": 1905,
    "preview": "/*\n  The Portfolio class holds data about the portfolio\n*/\n\nconst _ = require('lodash');\nconst async = require('async');"
  },
  {
    "path": "exchange/trigger.js",
    "chars": 1655,
    "preview": "// wraps around a low level trigger and feeds\n// it live market data.\n\nconst _ = require('lodash');\n\nconst exchangeUtils"
  },
  {
    "path": "exchange/triggers/index.js",
    "chars": 83,
    "preview": "const trailingStop = require('./trailingStop');\n\nmodule.exports = { trailingStop };"
  },
  {
    "path": "exchange/triggers/trailingStop.js",
    "chars": 1383,
    "preview": "const EventEmitter = require('events');\n\n// Note: as of now only supports trailing the price going up (after \n// a buy),"
  },
  {
    "path": "exchange/util/genMarketFiles/update-binance.js",
    "chars": 1466,
    "preview": "const _ = require('lodash');\nconst fs = require('fs');\nconst request = require('request-promise');\nconst Promise = requi"
  },
  {
    "path": "exchange/util/genMarketFiles/update-bitfinex.js",
    "chars": 1311,
    "preview": "const _ = require('lodash');\nconst fs = require('fs');\nconst request = require('request-promise');\nconst Promise = requi"
  },
  {
    "path": "exchange/util/genMarketFiles/update-coinbase.js",
    "chars": 1274,
    "preview": "const _ = require('lodash');\nconst fs = require('fs');\nconst request = require('request-promise');\nconst Promise = requi"
  },
  {
    "path": "exchange/util/genMarketFiles/update-coinfalcon.js",
    "chars": 1337,
    "preview": "const _ = require('lodash');\nconst fs = require('fs');\nconst request = require('request-promise');\nconst Promise = requi"
  },
  {
    "path": "exchange/util/genMarketFiles/update-kraken.js",
    "chars": 3567,
    "preview": "const _ = require('lodash');\nconst fs = require('fs');\nconst request = require('request-promise');\nconst Promise = requi"
  },
  {
    "path": "exchange/wrappers/DEBUG_exchange-simulator.js",
    "chars": 1553,
    "preview": "// Fake exchanges: used to test purposes to develop Gekko (works without internet).\n\nconst _ = require('lodash');\nconst "
  },
  {
    "path": "exchange/wrappers/binance-markets.json",
    "chars": 69524,
    "preview": "{\n  \"assets\": [\n    \"NULS\",\n    \"BNB\",\n    \"NEO\",\n    \"LINK\",\n    \"SALT\",\n    \"IOTA\",\n    \"ETC\",\n    \"AST\",\n    \"KNC\",\n "
  },
  {
    "path": "exchange/wrappers/binance.js",
    "chars": 13811,
    "preview": "const moment = require('moment');\nconst _ = require('lodash');\n\nconst Errors = require('../exchangeErrors');\nconst marke"
  },
  {
    "path": "exchange/wrappers/bitcoin-co-id.js.old",
    "chars": 9265,
    "preview": "var Bitcoincoid = require('bitcoin-co-id-update'),\r\n   _ = require('lodash'),\r\n   moment = require('moment'),\r\n   log = "
  },
  {
    "path": "exchange/wrappers/bitfinex-markets.json",
    "chars": 48307,
    "preview": "{\n  \"assets\": [\n    \"BTC\",\n    \"LTC\",\n    \"ETH\",\n    \"ETC\",\n    \"RRT\",\n    \"ZEC\",\n    \"XMR\",\n    \"DSH\",\n    \"XRP\",\n    \""
  },
  {
    "path": "exchange/wrappers/bitfinex.js",
    "chars": 8233,
    "preview": "\nconst Bitfinex = require(\"bitfinex-api-node\");\nconst _ = require('lodash');\nconst moment = require('moment');\n\nconst Er"
  },
  {
    "path": "exchange/wrappers/bitfinex_v2.js.prep",
    "chars": 6479,
    "preview": "// NOT USED, see: https://github.com/bitfinexcom/bitfinex-api-node/issues/321\n\nconst Bitfinex = require(\"bitfinex-api-no"
  },
  {
    "path": "exchange/wrappers/bitstamp.js.old",
    "chars": 8091,
    "preview": "var Bitstamp = require(\"bitstamp\");\nvar _ = require('lodash');\nvar moment = require('moment');\nvar log = require('../cor"
  },
  {
    "path": "exchange/wrappers/bittrex.js",
    "chars": 31895,
    "preview": "const Bittrex = require('node.bittrex.api');\nconst _ = require('lodash');\nconst moment = require('moment');\nconst retry "
  },
  {
    "path": "exchange/wrappers/btc-markets.js.old",
    "chars": 7117,
    "preview": "var BTCMarkets = require('btc-markets');\nvar _ = require('lodash');\nvar moment = require('moment');\nvar log = require('."
  },
  {
    "path": "exchange/wrappers/btcc.js.old",
    "chars": 4408,
    "preview": "var BTCChina = require('btc-china-fork');\nvar util = require('../core/util.js');\nvar _ = require('lodash');\nvar moment ="
  },
  {
    "path": "exchange/wrappers/bx.in.th.js.old",
    "chars": 2208,
    "preview": "var BitexthaiAPI = require('bitexthai');\nvar util = require('../core/util.js');\nvar _ = require('lodash');\nvar moment = "
  },
  {
    "path": "exchange/wrappers/cexio.js.old",
    "chars": 6046,
    "preview": "var CEXio = require('cexio'),\n   moment = require('moment'),\n    async = require('async'),\n        _ = require('lodash')"
  },
  {
    "path": "exchange/wrappers/coinbase-markets.json",
    "chars": 3581,
    "preview": "{\n  \"assets\": [\n    \"ETC\",\n    \"BTC\",\n    \"BCH\",\n    \"ETH\",\n    \"LTC\",\n    \"ZRX\"\n  ],\n  \"currencies\": [\n    \"EUR\",\n    \""
  },
  {
    "path": "exchange/wrappers/coinfalcon-markets.json",
    "chars": 4646,
    "preview": "{\n  \"assets\": [\n    \"IOT\",\n    \"ETH\",\n    \"LTC\",\n    \"BTC\",\n    \"NANO\",\n    \"BCH\",\n    \"KIN\",\n    \"TRX\",\n    \"CRPT\",\n   "
  },
  {
    "path": "exchange/wrappers/coinfalcon.js",
    "chars": 9749,
    "preview": "const moment = require('moment');\nconst _ = require('lodash');\nconst marketData = require('./coinfalcon-markets.json');\n"
  },
  {
    "path": "exchange/wrappers/coingi.js",
    "chars": 8948,
    "preview": "var Coingi = require('coingi');\nvar moment = require('moment');\nvar _ = require('lodash');\n\nvar util = require('../core/"
  },
  {
    "path": "exchange/wrappers/exmo-markets.json",
    "chars": 566,
    "preview": "{\n  \"assets\": [\n    \"BTC\",\n    \"ETH\"\n  ],\n  \"currencies\": [\n    \"EUR\",\n    \"USD\",\n    \"LTC\"\n  ],\n  \"markets\": [\n    {\n  "
  },
  {
    "path": "exchange/wrappers/exmo.js",
    "chars": 6242,
    "preview": "const _ = require('lodash');\nconst moment = require('moment');\nconst retry = require('../exchangeUtils').retry;\n\n\nconst "
  },
  {
    "path": "exchange/wrappers/gdax.js",
    "chars": 11833,
    "preview": "const Gdax = require('gdax');\nconst _ = require('lodash');\nconst moment = require('moment');\n\nconst errors = require('.."
  },
  {
    "path": "exchange/wrappers/gemini.js.old",
    "chars": 6423,
    "preview": "var Gemini = require('gemini-exchange-coffee-api/lib/gemini');\nvar util = require('../core/util.js');\nvar _ = require('l"
  },
  {
    "path": "exchange/wrappers/kraken-markets.json",
    "chars": 21107,
    "preview": "{\n  \"assets\": [\n    \"ADA\",\n    \"BCH\",\n    \"DASH\",\n    \"EOS\",\n    \"GNO\",\n    \"QTUM\",\n    \"USDT\",\n    \"ETC\",\n    \"ETH\",\n  "
  },
  {
    "path": "exchange/wrappers/kraken.js",
    "chars": 12560,
    "preview": "const Kraken = require('kraken-api');\nconst moment = require('moment');\nconst _ = require('lodash');\nconst exchangeUtils"
  },
  {
    "path": "exchange/wrappers/lakebtc.js",
    "chars": 3614,
    "preview": "var Lakebtc = require(\"lakebtc_nodejs\");\nvar util = require('../core/util.js');\nvar _ = require('lodash');\nvar moment = "
  },
  {
    "path": "exchange/wrappers/luno.js",
    "chars": 11597,
    "preview": "const Luno = require(\"bitx\");\nconst _ = require('lodash');\nconst moment = require('moment');\nconst node_util = require('"
  },
  {
    "path": "exchange/wrappers/mexbt.js.old",
    "chars": 4260,
    "preview": "var Mexbt = require(\"mexbt\");\nvar util = require('../core/util.js');\nvar _ = require('lodash');\nvar moment = require('mo"
  },
  {
    "path": "exchange/wrappers/mtgox.js.old",
    "chars": 6375,
    "preview": "// HERE FOR HISTORICAL PURPOSES\n\nvar MtGoxClient = require(\"mtgox-apiv2\");\nvar _ = require('lodash');\nvar moment = requi"
  },
  {
    "path": "exchange/wrappers/okcoin.js.old",
    "chars": 5180,
    "preview": "var OKCoin = require('okcoin-china');\nvar util = require('../core/util.js');\nvar _ = require('lodash');\nvar moment = req"
  },
  {
    "path": "exchange/wrappers/poloniex-markets.json",
    "chars": 47237,
    "preview": "{\n\t\"currencies\": [\"BTC\", \"ETH\", \"XMR\", \"USDT\", \"USDC\"],\n\t\"assets\": [\n    \"1CR\", \"ABY\", \"AC\", \"ACH\", \"ADN\", \"AEON\", \"AERO"
  },
  {
    "path": "exchange/wrappers/poloniex.js",
    "chars": 13845,
    "preview": "const Poloniex = require(\"gekko-broker-poloniex\");\nconst _ = require('lodash');\nconst moment = require('moment');\nconst "
  },
  {
    "path": "exchange/wrappers/quadriga-markets.json",
    "chars": 2130,
    "preview": "{\n  \"assets\": [\n    \"XBT\",\n    \"ETH\",\n    \"LTC\",\n    \"BCH\",\n    \"BTG\"\n  ],\n  \"currencies\": [\n    \"CAD\",\n    \"USD\",\n    \""
  },
  {
    "path": "exchange/wrappers/quadriga.js.old",
    "chars": 7702,
    "preview": "var QuadrigaCX = require('quadrigacx');\nvar moment = require('moment');\nvar util = require('../core/util');\nvar _ = requ"
  },
  {
    "path": "exchange/wrappers/therocktrading-markets.json",
    "chars": 2706,
    "preview": "{\n  \"assets\": [\n    \"ETH\",\n    \"LTC\",\n    \"BTC\",\n    \"BCH\",\n    \"EUR\",\n    \"PPC\",\n    \"ZEC\",\n    \"NOKU\",\n    \"FDZ\"\n  ],\n"
  },
  {
    "path": "exchange/wrappers/therocktrading.js",
    "chars": 7682,
    "preview": "const Therocktrading = require('therocktrading');\nconst _ = require('lodash');\nconst moment = require('moment');\nconst r"
  },
  {
    "path": "exchange/wrappers/wex.nz.js.old",
    "chars": 9933,
    "preview": "var WEX = require('node-wex');\n\nvar moment = require('moment');\nvar util = require('../core/util');\nvar _ = require('lod"
  },
  {
    "path": "exchange/wrappers/zaif.jp.js.old",
    "chars": 3653,
    "preview": "var Zaif = require(\"zaif.jp\");\nvar util = require('../core/util.js');\nvar _ = require('lodash');\nvar moment = require('m"
  },
  {
    "path": "gekko.js",
    "chars": 1962,
    "preview": "/*\n\n  Gekko is a Bitcoin trading bot for popular Bitcoin exchanges written \n  in node, it features multiple trading meth"
  },
  {
    "path": "importers/exchanges/binance.js",
    "chars": 1531,
    "preview": "const moment = require('moment');\nconst util = require('../../core/util.js');\nconst _ = require('lodash');\nconst log = r"
  },
  {
    "path": "importers/exchanges/bitfinex.js",
    "chars": 3676,
    "preview": "const Bitfinex = require('bitfinex-api-node');\nconst util = require('../../core/util.js');\nconst _ = require('lodash');\n"
  },
  {
    "path": "importers/exchanges/btcc.js",
    "chars": 1722,
    "preview": "var BTCChina = require('btc-china-fork');\nvar util = require('../../core/util.js');\nvar _ = require('lodash');\nvar momen"
  },
  {
    "path": "importers/exchanges/coinfalcon.js",
    "chars": 1205,
    "preview": "const moment = require('moment');\nconst util = require('../../core/util.js');\nconst _ = require('lodash');\nconst log = r"
  },
  {
    "path": "importers/exchanges/gdax.js",
    "chars": 4407,
    "preview": "const util = require('../../core/util.js');\nconst _ = require('lodash');\nconst moment = require('moment');\nconst log = r"
  },
  {
    "path": "importers/exchanges/kraken.js",
    "chars": 1673,
    "preview": "var _ = require('lodash');\nvar moment = require('moment');\n\nvar util = require('../../core/util.js');\nvar log = require("
  },
  {
    "path": "importers/exchanges/luno.js",
    "chars": 2764,
    "preview": "const moment = require('moment');\nconst util = require('../../core/util.js');\nconst _ = require('lodash');\nconst retry ="
  },
  {
    "path": "importers/exchanges/poloniex.js",
    "chars": 2863,
    "preview": "const util = require('../../core/util.js');\nconst _ = require('lodash');\nconst moment = require('moment');\nconst log = r"
  },
  {
    "path": "importers/exchanges/therocktrading.js",
    "chars": 2068,
    "preview": "const moment = require('moment');\nconst util = require('../../core/util');\nconst log = require('../../core/log');\nconst "
  },
  {
    "path": "logs/.gitignore",
    "chars": 13,
    "preview": "*\n!.gitignore"
  },
  {
    "path": "package.json",
    "chars": 1435,
    "preview": "{\n  \"name\": \"gekko\",\n  \"version\": \"0.6.8\",\n  \"description\": \"A bitcoin trading bot for auto trading at various exchanges"
  },
  {
    "path": "plugins/adviceLogger.js",
    "chars": 961,
    "preview": "var log = require('../core/log');\nvar moment = require('moment');\nvar _ = require('lodash');\nvar util = require('../core"
  },
  {
    "path": "plugins/backtestResultExporter.js",
    "chars": 3835,
    "preview": "// Small plugin that subscribes to some events, stores\n// them and sends it to the parent process.\n\nconst log = require("
  },
  {
    "path": "plugins/blotter.js",
    "chars": 3919,
    "preview": "const fsw = require('fs');\nconst _ = require('lodash');\nconst log = require('../core/log.js');\nconst util = require('../"
  },
  {
    "path": "plugins/campfire.js",
    "chars": 3635,
    "preview": "var _ = require('lodash');\nvar Moment = require('moment');\nvar Ranger = require('ranger');\n\nvar config = require('../cor"
  },
  {
    "path": "plugins/candleUploader.js",
    "chars": 1619,
    "preview": "const axios = require('axios');\nconst _ = require('lodash');\nconst log = require('../core/log.js');\nconst util = require"
  },
  {
    "path": "plugins/childToParent.js",
    "chars": 634,
    "preview": "// Small plugin that subscribes to some events, stores\n// them and sends it to the parent process.\n\nconst log = require("
  },
  {
    "path": "plugins/eventLogger.js",
    "chars": 522,
    "preview": "const log = require('../core/log');\nconst _ = require('lodash');\nconst subscriptions = require('../subscriptions');\ncons"
  },
  {
    "path": "plugins/ifttt.js",
    "chars": 2264,
    "preview": "const superagent = require('superagent');\nconst _ = require('lodash');\nconst log = require('../core/log.js');\nconst util"
  },
  {
    "path": "plugins/ircbot.js",
    "chars": 4139,
    "preview": "var log = require('../core/log');\nvar moment = require('moment');\nvar _ = require('lodash');\nvar config = require('../co"
  },
  {
    "path": "plugins/kodi.js",
    "chars": 1851,
    "preview": "/**\n * Created by billymcintosh on 24/12/17.\n */\n\nvar _ = require('lodash');\nvar request = require('request');\nvar log ="
  },
  {
    "path": "plugins/mailer.js",
    "chars": 3511,
    "preview": "var email = require(\"emailjs\");\nvar _ = require('lodash');\nvar log = require('../core/log.js');\nvar util = require('../c"
  },
  {
    "path": "plugins/mongodb/handle.js",
    "chars": 1341,
    "preview": "var mongojs = require('mongojs');\r\nvar mongoUtil = require('./util');\r\n\r\nvar util = require('../../core/util.js');\r\nvar "
  },
  {
    "path": "plugins/mongodb/reader.js",
    "chars": 3494,
    "preview": "var _ = require('lodash');\r\nvar util = require('../../core/util.js');\r\nvar log = require(`${util.dirs().core}log`);\r\n\r\nv"
  },
  {
    "path": "plugins/mongodb/scanner.js",
    "chars": 1260,
    "preview": "const async = require('async');\nvar _ = require('lodash');\nvar util = require('../../core/util.js');\nvar log = require(`"
  }
]

// ... and 171 more files (download for full content)

About this extraction

This page contains the full source code of the askmike/gekko GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 371 files (2.1 MB), approximately 563.1k tokens, and a symbol index with 2804 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!