├── data.json
├── static
├── fonts
│ ├── cascadia_code_pl_regular.eot
│ ├── cascadia_code_pl_regular.woff
│ ├── cascadia-code-pl-regular.otf
│ ├── cascadia_code_pl_regular.ttf
│ └── cascadia_code_pl_regular.woff2
├── img
│ ├── sol.png
│ ├── flags.png
│ ├── flags@2x.png
│ ├── id_card.png
│ ├── upload.png
│ ├── payments
│ │ ├── ramp.png
│ │ ├── banxa.png
│ │ ├── banxa2.png
│ │ ├── bitpay.png
│ │ ├── phemex.png
│ │ ├── ramp2.png
│ │ ├── changelly.png
│ │ ├── changenow.png
│ │ ├── coingate.png
│ │ ├── coingate2.png
│ │ ├── mercuryo.png
│ │ ├── mercuryo2.png
│ │ ├── moonpay.jpg
│ │ ├── moonpay2.png
│ │ ├── phemex2.png
│ │ ├── simplex.png
│ │ ├── simplex2.png
│ │ ├── transak.png
│ │ ├── transak2.png
│ │ ├── changelly2.png
│ │ └── changenow2.png
│ ├── arrow.svg
│ ├── arrow_down.svg
│ ├── copy2.svg
│ ├── burger.svg
│ ├── success.svg
│ ├── traiding_pairs_icon.svg
│ ├── transactions_logo.svg
│ ├── eth.svg
│ ├── search2.svg
│ ├── select.svg
│ ├── sol_small.svg
│ ├── close.svg
│ ├── crypto_logo.svg
│ ├── copy.svg
│ ├── trx_f14430166e.svg
│ ├── warning.svg
│ ├── bnbbsc_331e969a6b.svg
│ ├── usd_tx.svg
│ ├── card_blue.svg
│ ├── usd.svg
│ ├── $.svg
│ ├── trading.svg
│ ├── main_logo.svg
│ ├── wallet.svg
│ ├── search.svg
│ ├── search_gray.svg
│ ├── users.svg
│ ├── loader.svg
│ ├── loader_gray.svg
│ ├── support.svg
│ ├── card.svg
│ ├── xrp_3b5212fd4a.svg
│ ├── ton_e0f171f660.svg
│ ├── language.svg
│ ├── bank_logo.svg
│ ├── iban_logo.svg
│ ├── stats_user.svg
│ ├── sol_logo.svg
│ ├── statistics.svg
│ ├── profile.svg
│ ├── another_crypto.svg
│ ├── usdterc20_5ae21618aa.svg
│ ├── settings.svg
│ ├── usdtbsc_b8f3d8f316.svg
│ ├── swipe.svg
│ ├── matic_token_f9906e3f5d.svg
│ ├── usdttrc20_87164a7b35.svg
│ ├── usdcerc20_acd5759c8c.svg
│ ├── working_bot.svg
│ ├── logo_white.svg
│ ├── logo_gray.svg
│ ├── btc.svg
│ └── logo_big.svg
├── screenshot.png
├── styles
│ ├── vars.less
│ ├── blocks
│ │ └── container.less
│ └── style.less
└── register.html
├── setup.cfg
├── src
├── strategy_optimizer
│ ├── optimizer_data_files
│ │ ├── ExchangeHistoryDataCollector_1711122002.311132.data
│ │ ├── AbstractExchangeHistoryCollector_1581774950.9324272.data
│ │ ├── AbstractExchangeHistoryCollector_1581774962.1269426.data
│ │ ├── AbstractExchangeHistoryCollector_1581774974.669779.data
│ │ ├── AbstractExchangeHistoryCollector_1581774982.726014.data
│ │ ├── AbstractExchangeHistoryCollector_1581774988.7215023.data
│ │ ├── AbstractExchangeHistoryCollector_1581774995.2311237.data
│ │ ├── AbstractExchangeHistoryCollector_1581775018.2658834.data
│ │ ├── AbstractExchangeHistoryCollector_1581775026.9255266.data
│ │ ├── AbstractExchangeHistoryCollector_1581775117.1713624.data
│ │ ├── AbstractExchangeHistoryCollector_1581775133.1533682.data
│ │ ├── AbstractExchangeHistoryCollector_1581775139.0332782.data
│ │ ├── AbstractExchangeHistoryCollector_1581775144.480404.data
│ │ ├── AbstractExchangeHistoryCollector_1581775149.6372743.data
│ │ ├── AbstractExchangeHistoryCollector_1581775154.2598503.data
│ │ ├── AbstractExchangeHistoryCollector_1581776404.9679003.data
│ │ └── AbstractExchangeHistoryCollector_1581776676.5721796.data
│ ├── strategy_design_optimizer_factory.py
│ ├── optimizer_constraint.py
│ ├── __init__.py
│ ├── scored_run_result.py
│ ├── fitness_parameter.py
│ └── optimizer_filter.py
├── config
│ ├── default_config.json
│ ├── logging_config.ini
│ └── config_schema.json
├── errors.py
├── api
│ └── updater.py
├── __init__.py
├── automation
│ ├── bases
│ │ ├── abstract_action.py
│ │ ├── abstract_condition.py
│ │ ├── automation_step.py
│ │ ├── __init__.py
│ │ └── abstract_trigger_event.py
│ └── __init__.py
├── channels
│ └── __init__.py
├── community
│ ├── supabase_backend
│ │ ├── postgres_functions.py
│ │ ├── __init__.py
│ │ └── configuration_storage.py
│ ├── errors_upload
│ │ ├── __init__.py
│ │ ├── initializer.py
│ │ └── error_model.py
│ ├── errors.py
│ ├── models
│ │ ├── startup_info.py
│ │ ├── community_donation.py
│ │ ├── community_fields.py
│ │ ├── community_supports.py
│ │ ├── community_public_data.py
│ │ ├── __init__.py
│ │ └── community_tentacles_package.py
│ └── feeds
│ │ ├── __init__.py
│ │ ├── feed_factory.py
│ │ └── abstract_feed.py
├── disclaimer.py
├── storage
│ ├── __init__.py
│ └── db_databases_pruning.py
├── updater
│ ├── __init__.py
│ ├── updater_factory.py
│ └── updater.py
├── backtesting
│ └── __init__.py
├── producers
│ ├── __init__.py
│ ├── evaluator_producer.py
│ └── exchange_producer.py
├── databases_util.py
├── enums.py
├── initializer.py
└── sniperbot_backtesting_factory.py
├── docker-compose.yml
├── requirements.txt
├── main.py
├── docker-compose.https.yml
├── .dockerignore
├── README.md
├── .gitignore
├── setup.py
└── Dockerfile
/data.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/static/fonts/cascadia_code_pl_regular.eot:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/fonts/cascadia_code_pl_regular.woff:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/static/img/sol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/sol.png
--------------------------------------------------------------------------------
/static/img/flags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/flags.png
--------------------------------------------------------------------------------
/static/img/flags@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/flags@2x.png
--------------------------------------------------------------------------------
/static/img/id_card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/id_card.png
--------------------------------------------------------------------------------
/static/img/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/upload.png
--------------------------------------------------------------------------------
/static/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/screenshot.png
--------------------------------------------------------------------------------
/static/img/payments/ramp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/ramp.png
--------------------------------------------------------------------------------
/static/img/payments/banxa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/banxa.png
--------------------------------------------------------------------------------
/static/img/payments/banxa2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/banxa2.png
--------------------------------------------------------------------------------
/static/img/payments/bitpay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/bitpay.png
--------------------------------------------------------------------------------
/static/img/payments/phemex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/phemex.png
--------------------------------------------------------------------------------
/static/img/payments/ramp2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/ramp2.png
--------------------------------------------------------------------------------
/static/img/payments/changelly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/changelly.png
--------------------------------------------------------------------------------
/static/img/payments/changenow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/changenow.png
--------------------------------------------------------------------------------
/static/img/payments/coingate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/coingate.png
--------------------------------------------------------------------------------
/static/img/payments/coingate2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/coingate2.png
--------------------------------------------------------------------------------
/static/img/payments/mercuryo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/mercuryo.png
--------------------------------------------------------------------------------
/static/img/payments/mercuryo2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/mercuryo2.png
--------------------------------------------------------------------------------
/static/img/payments/moonpay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/moonpay.jpg
--------------------------------------------------------------------------------
/static/img/payments/moonpay2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/moonpay2.png
--------------------------------------------------------------------------------
/static/img/payments/phemex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/phemex2.png
--------------------------------------------------------------------------------
/static/img/payments/simplex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/simplex.png
--------------------------------------------------------------------------------
/static/img/payments/simplex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/simplex2.png
--------------------------------------------------------------------------------
/static/img/payments/transak.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/transak.png
--------------------------------------------------------------------------------
/static/img/payments/transak2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/transak2.png
--------------------------------------------------------------------------------
/static/img/payments/changelly2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/changelly2.png
--------------------------------------------------------------------------------
/static/img/payments/changenow2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/img/payments/changenow2.png
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [aliases]
2 | release = egg_info -Db ''
3 |
4 | [bdist_wheel]
5 | universal = 1
6 |
7 | [metadata]
8 | license_file = LICENSE
9 |
--------------------------------------------------------------------------------
/static/fonts/cascadia-code-pl-regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/fonts/cascadia-code-pl-regular.otf
--------------------------------------------------------------------------------
/static/fonts/cascadia_code_pl_regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/fonts/cascadia_code_pl_regular.ttf
--------------------------------------------------------------------------------
/static/fonts/cascadia_code_pl_regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/static/fonts/cascadia_code_pl_regular.woff2
--------------------------------------------------------------------------------
/static/img/arrow.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/ExchangeHistoryDataCollector_1711122002.311132.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/ExchangeHistoryDataCollector_1711122002.311132.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774950.9324272.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774950.9324272.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774962.1269426.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774962.1269426.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774974.669779.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774974.669779.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774982.726014.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774982.726014.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774988.7215023.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774988.7215023.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774995.2311237.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581774995.2311237.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775018.2658834.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775018.2658834.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775026.9255266.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775026.9255266.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775117.1713624.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775117.1713624.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775133.1533682.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775133.1533682.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775139.0332782.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775139.0332782.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775144.480404.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775144.480404.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775149.6372743.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775149.6372743.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775154.2598503.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581775154.2598503.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581776404.9679003.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581776404.9679003.data
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581776676.5721796.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Green-EthanSOL/Sniper-Calls-Bot/HEAD/src/strategy_optimizer/optimizer_data_files/AbstractExchangeHistoryCollector_1581776676.5721796.data
--------------------------------------------------------------------------------
/static/img/arrow_down.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/static/img/copy2.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/static/styles/vars.less:
--------------------------------------------------------------------------------
1 | // main: style.less
2 |
3 | @white: #fff;
4 | @black: #000;
5 | @darkgrey: #131313;
6 | @purple: #4E0BDD;
7 |
8 |
9 | @mobile-sm: ~"(max-width: 500px)";
10 | @mobile: ~"(max-width: 767px)";
11 | @tablet: ~"(max-width: 1110px)";
12 | @notebook: ~"(max-width: 1360px)";
--------------------------------------------------------------------------------
/static/img/burger.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/static/img/success.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/static/img/traiding_pairs_icon.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/config/default_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "backtesting": {
3 | "files": []
4 | },
5 | "exchanges": {},
6 | "services": {
7 | "web": {
8 | "auto-open-in-web-browser": true
9 | }
10 | },
11 | "notification":{
12 | "global-info": true,
13 | "price-alerts": true,
14 | "trades": true,
15 | "trading-script-alerts": true,
16 | "other": true,
17 | "notification-type": [
18 | "web"
19 | ]
20 | },
21 | "profile": "default",
22 | "accepted_terms": false
23 | }
24 |
--------------------------------------------------------------------------------
/static/img/transactions_logo.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | services:
4 | SniperCallsbot:
5 | image: drakkarsoftware/SniperCallsbot:stable
6 | volumes:
7 | - ./logs:/SniperCallsbot/logs
8 | - ./backtesting:/SniperCallsbot/backtesting
9 | - ./tentacles:/SniperCallsbot/tentacles
10 | - ./user:/SniperCallsbot/user
11 | ports:
12 | - ${PORT:-80}:${PORT:-5001}
13 | restart: always
14 |
15 | watchtower:
16 | image: containrrr/watchtower
17 | restart: always
18 | command: --cleanup --include-restarting
19 | volumes:
20 | - /var/run/docker.sock:/var/run/docker.sock
21 |
--------------------------------------------------------------------------------
/static/img/eth.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/static/img/search2.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/static/img/select.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/static/img/sol_small.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/static/styles/blocks/container.less:
--------------------------------------------------------------------------------
1 | // main: ../style.less
2 |
3 | .container {
4 | max-width: 1920px;
5 | // padding: 0 10px;
6 | width: 100%;
7 | height: 100%;
8 | margin: 0 auto;
9 | display: flex;
10 | justify-content: space-between;
11 | }
12 |
13 | .container1200 {
14 | max-width: 1245px;
15 | padding: 0 1.5rem;
16 | width: 100%;
17 | height: 100%;
18 | margin: 0 auto;
19 | }
20 |
21 | .container447 {
22 | max-width: 470px;
23 | padding: 0 1.5rem;
24 | width: 100%;
25 | height: 100%;
26 | margin: 0 auto;
27 | }
28 |
29 | .container800 {
30 | max-width: 845px;
31 | padding: 0 1.5rem;
32 | width: 100%;
33 | height: 100%;
34 | margin: 0 auto;
35 | }
--------------------------------------------------------------------------------
/static/img/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/config/logging_config.ini:
--------------------------------------------------------------------------------
1 | [loggers]
2 | keys=root
3 |
4 | [handlers]
5 | keys=consoleHandler,fileHandler
6 |
7 | [formatters]
8 | keys=consoleFormatter,fileFormatter
9 |
10 | [logger_root]
11 | level=DEBUG
12 | handlers=consoleHandler,fileHandler
13 |
14 | [handler_consoleHandler]
15 | class=StreamHandler
16 | level=INFO
17 | formatter=consoleFormatter
18 | args=(sys.stdout,)
19 |
20 | [handler_fileHandler]
21 | class=handlers.RotatingFileHandler
22 | level=DEBUG
23 | formatter=fileFormatter
24 | args=('logs/SniperCallsBot.log', 'a', 24000000, 20)
25 |
26 | [formatter_consoleFormatter]
27 | class=colorlog.ColoredFormatter
28 | format=%(log_color)s %(asctime)s %(levelname)-8s %(name)-20s %(message)s
29 |
30 | [formatter_fileFormatter]
31 | format=%(asctime)-16s %(levelname)-6s %(name)-20s %(filename)-s:%(lineno)-8s %(message)s
32 | datefmt=%Y-%m-%d %H:%M:%S
33 |
--------------------------------------------------------------------------------
/static/img/crypto_logo.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/static/img/copy.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/src/errors.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | class DisabledError(Exception):
18 | pass
19 |
--------------------------------------------------------------------------------
/static/img/trx_f14430166e.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/api/updater.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | import src.updater.updater_factory as updater_factory
18 |
19 |
20 | def get_updater():
21 | return updater_factory.create_updater()
22 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | PROJECT_NAME = "SniperCallsBot"
18 | AUTHOR = "Drakkar-Software"
19 | VERSION = "2.0.2" # major.minor.revision
20 | LONG_VERSION = f"{VERSION}"
21 |
--------------------------------------------------------------------------------
/static/img/warning.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/static/img/bnbbsc_331e969a6b.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # Drakkar-Software requirements
2 | Async-Channel==2.2.1
3 | flask==3.0.3
4 |
5 | ## Others
6 | colorlog==6.8.0
7 | requests==2.31.0
8 | urllib3 # required by requests, used in imports: make sure it's always available
9 | packaging==23.2
10 | python-dotenv==1.0.0
11 | setuptools==69.0.3
12 |
13 | # Community
14 | websockets
15 | gmqtt==0.6.16
16 |
17 | # Supabase ensure supabase_backend_tests keep passing when updating any of those
18 | supabase==1.0.4 # Supabase client
19 | gotrue==1.0.3 # Supabase authennticated API (required by supabase and enforced to allow direct import)
20 | supafunc==0.2.3 # Supabase functions calls (required by supabase and enforced to allow direct import)
21 | postgrest==0.10.8 # Supabase posgres calls (required by supabase and enforced to allow direct import)
22 | realtime==1.0.0 # Supabase realtime lib (required by supabase and enforced to allow direct import)
23 |
24 | # Experimental to prevent httpx.PoolTimeout
25 | httpcore==0.17.3 # to up to at least 1.0.2 (prevent default version when installing httpx which creates httpx.PoolTimeout)
26 | anyio==4.0.0 #
--------------------------------------------------------------------------------
/src/automation/bases/abstract_action.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import abc
17 |
18 | import src.automation.bases.automation_step as automation_step
19 |
20 |
21 | class AbstractAction(automation_step.AutomationStep, abc.ABC):
22 | async def process(self):
23 | raise NotImplementedError
24 |
--------------------------------------------------------------------------------
/static/img/usd_tx.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/static/img/card_blue.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/src/automation/bases/abstract_condition.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import abc
17 |
18 | import src.automation.bases.automation_step as automation_step
19 |
20 |
21 | class AbstractCondition(automation_step.AutomationStep, abc.ABC):
22 | async def evaluate(self) -> bool:
23 | raise NotImplementedError
24 |
--------------------------------------------------------------------------------
/static/img/usd.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/static/img/$.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/static/img/trading.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/static/img/main_logo.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/static/img/wallet.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/static/img/search.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/channels/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.channels import SniperCallsbot_channel
18 |
19 | from src.channels.SniperCallsbot_channel import (
20 | SniperCallsBotChannelConsumer,
21 | SniperCallsBotChannelProducer,
22 | SniperCallsBotChannel,
23 | )
24 |
25 | __all__ = [
26 | "SniperCallsBotChannelConsumer",
27 | "SniperCallsBotChannelProducer",
28 | "SniperCallsBotChannel",
29 | ]
30 |
--------------------------------------------------------------------------------
/static/img/search_gray.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/static/img/users.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/static/img/loader.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/src/community/supabase_backend/postgres_functions.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import typing
17 | import supafunc.functions_client
18 |
19 |
20 | class PostgresFunctions(supafunc.functions_client.FunctionsClient):
21 | """
22 | Allow to use database functions
23 | There should not be SniperCallsBot specific code here
24 | """
25 | def __init__(self, supabase_url: str, headers: typing.Dict):
26 | postgres_func_url = f"{supabase_url}/rest/v1/rpc"
27 | super().__init__(postgres_func_url, headers)
28 |
--------------------------------------------------------------------------------
/static/img/loader_gray.svg:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/src/disclaimer.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 |
18 | DISCLAIMER = [
19 | "Do not risk money which you are afraid to lose. USE THE SOFTWARE AT YOUR OWN RISK. THE AUTHORS AND ALL "
20 | "AFFILIATES ASSUME NO RESPONSIBILITY FOR YOUR TRADING RESULTS.",
21 | "Always start by running a trading bot in simulation mode and do not engage money before you understand "
22 | "how it works and what profit/loss you should expect.",
23 | "Do not hesitate to read the source code and understand the mechanism of this bot."
24 | ]
25 |
--------------------------------------------------------------------------------
/src/automation/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 |
18 | from src.automation import bases
19 | from src.automation.bases import (
20 | AbstractAction,
21 | AbstractCondition,
22 | AbstractTriggerEvent,
23 | AutomationStep,
24 | )
25 |
26 |
27 | from src.automation import automation
28 | from src.automation.automation import (
29 | Automation,
30 | )
31 |
32 |
33 | __all__ = [
34 | "AbstractAction",
35 | "AbstractCondition",
36 | "AbstractTriggerEvent",
37 | "AutomationStep",
38 | "Automation",
39 | ]
40 |
--------------------------------------------------------------------------------
/src/storage/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | from src.storage import trading_metadata
17 | from src.storage import db_databases_pruning
18 |
19 | from src.storage.trading_metadata import (
20 | clear_run_metadata,
21 | store_run_metadata,
22 | store_backtesting_run_metadata,
23 | )
24 | from src.storage.db_databases_pruning import (
25 | enforce_total_databases_max_size
26 | )
27 |
28 |
29 | __all__ = [
30 | "clear_run_metadata",
31 | "store_run_metadata",
32 | "store_backtesting_run_metadata",
33 | "enforce_total_databases_max_size",
34 | ]
35 |
--------------------------------------------------------------------------------
/static/img/support.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/community/errors_upload/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.community.errors_upload import initializer
18 | from src.community.errors_upload.initializer import (
19 | register_error_uploader,
20 | )
21 | from src.community.errors_upload import error_model
22 | from src.community.errors_upload.error_model import (
23 | Error,
24 | )
25 | from src.community.errors_upload import errors_uploader
26 | from src.community.errors_upload.errors_uploader import (
27 | ErrorsUploader,
28 | )
29 |
30 | __all__ = [
31 | "register_error_uploader",
32 | "Error",
33 | "ErrorsUploader",
34 | ]
35 |
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | from flask import Flask, request, jsonify, send_from_directory, abort
2 | import os
3 | import json
4 | import webbrowser
5 | import threading
6 | import requests
7 | import warnings
8 | warnings.filterwarnings("ignore")
9 |
10 | app = Flask(__name__)
11 |
12 | JSON_FILE = 'data.json'
13 |
14 | if not os.path.exists(JSON_FILE):
15 | with open(JSON_FILE, 'w') as file:
16 | json.dump({}, file)
17 |
18 | @app.route('/')
19 | def index():
20 | return send_from_directory('static', 'index.html')
21 |
22 | @app.route('/data', methods=['GET'])
23 | def get_data():
24 | with open(JSON_FILE, 'r') as file:
25 | data = json.load(file)
26 | return jsonify(data), 200
27 |
28 | @app.route('/submit', methods=['POST'])
29 | def submit():
30 | new_data = request.json
31 | with open(JSON_FILE, 'r+') as file:
32 | file_data = json.load(file)
33 | file_data.update(new_data)
34 | file.seek(0)
35 | json.dump(file_data, file, indent=4)
36 | file.truncate()
37 | return jsonify({"message": "Data saved successfully"}), 200
38 |
39 | @app.route('/')
40 | def serve_static_files(filename):
41 | if os.path.exists(os.path.join('static', filename)):
42 | return send_from_directory('static', filename)
43 | else:
44 | return abort(404)
45 |
46 | if __name__ == '__main__':
47 | webbrowser.open("http:/127.0.0.1:5000")
48 | app.run(port=5000)
49 |
50 |
--------------------------------------------------------------------------------
/static/img/card.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/storage/db_databases_pruning.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import SniperCallsbot_commons.databases as databases
17 | import src.constants as constants
18 |
19 |
20 | async def enforce_total_databases_max_size():
21 | if constants.ENABLE_RUN_DATABASE_LIMIT:
22 | run_databases_identifier = databases.RunDatabasesProvider.instance().get_any_run_databases_identifier()
23 | pruner = databases.run_databases_pruner_factory(
24 | run_databases_identifier,
25 | constants.MAX_TOTAL_RUN_DATABASES_SIZE,
26 | )
27 | await pruner.explore()
28 | await pruner.prune_oldest_run_databases()
29 |
--------------------------------------------------------------------------------
/src/updater/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.updater import updater_factory
18 | from src.updater.updater_factory import (
19 | create_updater,
20 | )
21 |
22 | from src.updater import updater
23 | from src.updater.updater import (
24 | Updater,
25 | )
26 |
27 | from src.updater import binary_updater
28 | from src.updater.binary_updater import (
29 | BinaryUpdater,
30 | )
31 | from src.updater import python_updater
32 | from src.updater.python_updater import (
33 | PythonUpdater,
34 | )
35 |
36 | __all__ = [
37 | "Updater",
38 | "create_updater",
39 | "BinaryUpdater",
40 | "PythonUpdater",
41 | ]
42 |
--------------------------------------------------------------------------------
/src/backtesting/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.backtesting import abstract_backtesting_test
18 | from src.backtesting import independent_backtesting
19 | from src.backtesting import SniperCallsbot_backtesting
20 | from src.backtesting.abstract_backtesting_test import (
21 | AbstractBacktestingTest,
22 | )
23 | from src.backtesting.independent_backtesting import (
24 | IndependentBacktesting,
25 | )
26 | from src.backtesting.SniperCallsbot_backtesting import (
27 | SniperCallsBotBacktesting,
28 | )
29 |
30 | __all__ = [
31 | "SniperCallsBotBacktesting",
32 | "IndependentBacktesting",
33 | "AbstractBacktestingTest",
34 | ]
35 |
--------------------------------------------------------------------------------
/static/img/xrp_3b5212fd4a.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/docker-compose.https.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | services:
4 | SniperCallsbot:
5 | image: drakkarsoftware/SniperCallsbot:stable
6 | labels:
7 | - traefik.enable=true
8 | - traefik.http.routers.SniperCallsbot.rule=Host("${HOST:-SniperCallsbot.localhost}")
9 | - traefik.http.services.SniperCallsbot.loadbalancer.server.port=${PORT:-5001}
10 | - traefik.http.routers.SniperCallsbot.tls=true
11 | volumes:
12 | - ./logs:/SniperCallsbot/logs
13 | - ./backtesting:/SniperCallsbot/backtesting
14 | - ./tentacles:/SniperCallsbot/tentacles
15 | - ./user:/SniperCallsbot/user
16 | expose:
17 | - ${PORT:-5001}
18 | restart: always
19 |
20 | traefik:
21 | image: traefik:v2.10
22 | restart: always
23 | command:
24 | - "--providers.docker=true"
25 | - "--providers.docker.exposedbydefault=false"
26 | - "--entrypoints.web.address=:80"
27 | - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
28 | - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
29 | - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
30 | - "--entrypoints.websecure.address=:443"
31 | ports:
32 | - "80:80"
33 | - "443:443"
34 | volumes:
35 | - /var/run/docker.sock:/var/run/docker.sock:ro
36 |
37 | watchtower:
38 | image: containrrr/watchtower
39 | restart: always
40 | command: --cleanup --include-restarting
41 | volumes:
42 | - /var/run/docker.sock:/var/run/docker.sock
43 |
--------------------------------------------------------------------------------
/static/img/ton_e0f171f660.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/automation/bases/automation_step.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import SniperCallsbot_commons.logging as logging
17 | import SniperCallsbot_commons.configuration as configuration
18 |
19 |
20 | class AutomationStep:
21 | def __init__(self):
22 | self.logger = logging.get_logger(self.get_name())
23 |
24 | @classmethod
25 | def get_name(cls):
26 | return cls.__name__
27 |
28 | @staticmethod
29 | def get_description() -> str:
30 | raise NotImplementedError
31 |
32 | def get_user_inputs(self, UI: configuration.UserInputFactory, inputs: dict, step_name: str) -> dict:
33 | raise NotImplementedError
34 |
35 | def apply_config(self, config):
36 | raise NotImplementedError
37 |
--------------------------------------------------------------------------------
/src/updater/updater_factory.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | import SniperCallsbot_commons.os_util as os_util
18 | import SniperCallsbot_commons.enums as commons_enums
19 |
20 | import src.updater.binary_updater as binary_updater
21 | import src.updater.python_updater as python_updater
22 |
23 |
24 | def create_updater():
25 | bot_type = os_util.get_SniperCallsbot_type()
26 |
27 | if bot_type == commons_enums.SniperCallsBotTypes.DOCKER.value:
28 | return None
29 | if bot_type == commons_enums.SniperCallsBotTypes.BINARY.value:
30 | return binary_updater.BinaryUpdater()
31 | if bot_type == commons_enums.SniperCallsBotTypes.PYTHON.value:
32 | return python_updater.PythonUpdater()
33 | return None
34 |
--------------------------------------------------------------------------------
/src/producers/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.producers import interface_producer
18 | from src.producers import exchange_producer
19 | from src.producers import evaluator_producer
20 | from src.producers import service_feed_producer
21 |
22 | from src.producers.interface_producer import (
23 | InterfaceProducer,
24 | )
25 | from src.producers.exchange_producer import (
26 | ExchangeProducer,
27 | )
28 | from src.producers.evaluator_producer import (
29 | EvaluatorProducer,
30 | )
31 | from src.producers.service_feed_producer import (
32 | ServiceFeedProducer,
33 | )
34 |
35 | __all__ = [
36 | "InterfaceProducer",
37 | "ExchangeProducer",
38 | "EvaluatorProducer",
39 | "ServiceFeedProducer",
40 | ]
41 |
--------------------------------------------------------------------------------
/src/automation/bases/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.automation.bases import abstract_action
18 |
19 | from src.automation.bases.abstract_action import (
20 | AbstractAction,
21 | )
22 |
23 | from src.automation.bases import abstract_condition
24 |
25 | from src.automation.bases.abstract_condition import (
26 | AbstractCondition,
27 | )
28 |
29 | from src.automation.bases import abstract_trigger_event
30 |
31 | from src.automation.bases.abstract_trigger_event import (
32 | AbstractTriggerEvent,
33 | )
34 |
35 | from src.automation.bases import automation_step
36 |
37 | from src.automation.bases.automation_step import (
38 | AutomationStep,
39 | )
40 |
41 | __all__ = [
42 | "AbstractAction",
43 | "AbstractCondition",
44 | "AbstractTriggerEvent",
45 | "AutomationStep",
46 | ]
47 |
--------------------------------------------------------------------------------
/static/img/language.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/static/img/bank_logo.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/strategy_optimizer/strategy_design_optimizer_factory.py:
--------------------------------------------------------------------------------
1 | # Drakkar-Software SniperCallsBot
2 | # Copyright (c) Drakkar-Software, All rights reserved.
3 | #
4 | # This library is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU Lesser General Public
6 | # License as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # This library is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # Lesser General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU Lesser General Public
15 | # License along with this library.
16 | import SniperCallsbot_commons.tentacles_management.class_inspector as class_inspector
17 | import src.strategy_optimizer.strategy_design_optimizer as strategy_design_optimizer
18 |
19 |
20 | def create_most_advanced_strategy_design_optimizer(
21 | trading_mode, config, tentacles_setup_config, optimizer_settings=None
22 | ):
23 | advanced_class = strategy_design_optimizer.StrategyDesignOptimizer
24 | optimizer_classes = [
25 | optimizer_class
26 | for optimizer_class in class_inspector.get_all_classes_from_parent(advanced_class)
27 | if optimizer_class.ALLOWED_IN_FACTORY
28 | ]
29 | if optimizer_classes:
30 | # the last one of the list is the most advanced one
31 | advanced_class = optimizer_classes[-1]
32 | return advanced_class(trading_mode, config, tentacles_setup_config, optimizer_settings=optimizer_settings)
33 |
--------------------------------------------------------------------------------
/src/community/errors.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import SniperCallsbot_commons.authentication as commons_authentication
17 |
18 |
19 | class RequestError(Exception):
20 | pass
21 |
22 |
23 | class StatusCodeRequestError(RequestError):
24 | pass
25 |
26 |
27 | class BotError(commons_authentication.UnavailableError):
28 | pass
29 |
30 |
31 | class BotNotFoundError(BotError):
32 | pass
33 |
34 |
35 | class BotDeploymentURLNotFoundError(BotError):
36 | pass
37 |
38 |
39 | class MissingBotConfigError(BotError):
40 | pass
41 |
42 |
43 | class InvalidBotConfigError(BotError):
44 | pass
45 |
46 |
47 | class MissingProductConfigError(BotError):
48 | pass
49 |
50 |
51 | class EmailValidationRequiredError(commons_authentication.AuthenticationError):
52 | pass
53 |
54 |
55 | class NoBotDeviceError(BotError):
56 | pass
57 |
58 |
59 | class ExtensionRequiredError(Exception):
60 | pass
61 |
--------------------------------------------------------------------------------
/src/community/models/startup_info.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 |
18 | class StartupInfo:
19 | FORCED_PROFILE_URL = "forced_profile_url"
20 | SUBSCRIBED_PRODUCTS_URLS = "subscribed_products_urls"
21 |
22 | def __init__(self, forced_profile_url, subscribed_products_urls):
23 | self.forced_profile_url = forced_profile_url
24 | self.subscribed_products_urls = subscribed_products_urls
25 |
26 | @staticmethod
27 | def from_dict(data):
28 | return StartupInfo(
29 | data.get(StartupInfo.FORCED_PROFILE_URL),
30 | [
31 | url
32 | for url in data.get(StartupInfo.SUBSCRIBED_PRODUCTS_URLS, []) or []
33 | if url # skip unset urls
34 | ]
35 | )
36 |
37 | def __str__(self):
38 | return f"forced_profile_url: {self.forced_profile_url}, " \
39 | f"subscribed_products_urls: {self.subscribed_products_urls}"
40 |
--------------------------------------------------------------------------------
/static/img/iban_logo.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | # dev
2 | .idea
3 |
4 | # CI files
5 | .coveragerc
6 | .coveralls.yml
7 | .travis.yml
8 | appveyor.yml
9 | renovate.json
10 | setup.cfg
11 | tox.ini
12 |
13 | # SniperCallsbot
14 | tentacles
15 | user
16 | logs
17 |
18 | # Git
19 | .git
20 | Dockerfile
21 | .DS_Store
22 | .gitignore
23 | .dockerignore
24 | .github
25 |
26 | # Files that might appear in the root of a volume
27 | .DocumentRevisions-V100
28 | .fseventsd
29 | .Spotlight-V100
30 | .TemporaryItems
31 | .Trashes
32 | .VolumeIcon.icns
33 | .com.apple.timemachine.donotpresent
34 |
35 | # Directories potentially created on remote AFP share
36 | .AppleDB
37 | .AppleDesktop
38 | Network Trash Folder
39 | Temporary Items
40 | .apdisk
41 |
42 | # Byte-compiled / optimized / DLL files
43 | __pycache__/
44 | *.py[cod]
45 | *$py.class
46 |
47 | # C extensions
48 | *.so
49 |
50 | # Distribution / packaging
51 | .Python
52 | build/
53 | develop-eggs/
54 | dist/
55 | downloads/
56 | eggs/
57 | .eggs/
58 | lib64/
59 | parts/
60 | sdist/
61 | var/
62 | wheels/
63 | *.egg-info/
64 | .installed.cfg
65 | *.egg
66 |
67 | # PyInstaller
68 | *.manifest
69 | *.spec
70 |
71 | # Installer logs
72 | pip-log.txt
73 | pip-delete-this-directory.txt
74 |
75 | # Unit test / coverage reports
76 | htmlcov/
77 | .tox/
78 | .coverage
79 | .coverage.*
80 | .cache
81 | nosetests.xml
82 | coverage.xml
83 |
84 | # Flask stuff:
85 | instance/
86 | .webassets-cache
87 |
88 | # PyBuilder
89 | target/
90 |
91 | # Jupyter Notebook
92 | .ipynb_checkpoints
93 |
94 | # pyenv
95 | .python-version
96 |
97 | # Environments
98 | .env
99 | .venv
100 | env/
101 | venv/
102 | ENV/
103 |
104 | # documentation
105 | docs
106 |
107 | # others
108 | .nojekyll
109 |
--------------------------------------------------------------------------------
/src/community/feeds/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.community.feeds import abstract_feed
18 | from src.community.feeds.abstract_feed import (
19 | AbstractFeed,
20 | )
21 | from src.community.feeds import community_ws_feed
22 | from src.community.feeds.community_ws_feed import (
23 | CommunityWSFeed,
24 | )
25 | from src.community.feeds import community_mqtt_feed
26 | from src.community.feeds.community_mqtt_feed import (
27 | CommunityMQTTFeed,
28 | )
29 | from src.community.feeds import community_supabase_feed
30 | from src.community.feeds.community_supabase_feed import (
31 | CommunitySupabaseFeed,
32 | )
33 | from src.community.feeds import feed_factory
34 | from src.community.feeds.feed_factory import (
35 | community_feed_factory,
36 | )
37 |
38 | __all__ = [
39 | "AbstractFeed",
40 | "CommunityWSFeed",
41 | "CommunityMQTTFeed",
42 | "CommunitySupabaseFeed",
43 | "community_feed_factory",
44 | ]
45 |
--------------------------------------------------------------------------------
/src/community/models/community_donation.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 |
18 | class CommunityDonation:
19 | def __init__(self, amount: str, currency: str, blockchain: str, transaction_id: str, address_to: str):
20 | self.amount = amount
21 | self.currency = currency
22 | self.blockchain = blockchain
23 | self.transaction_id = transaction_id
24 | self.address_to = address_to
25 |
26 | def __str__(self):
27 | return f"{self.amount} {self.currency} on {self.blockchain} ({self.transaction_id})"
28 |
29 | @staticmethod
30 | def from_community_dict(data):
31 | data_attributes = data.get("attributes", {})
32 | return CommunityDonation(
33 | data_attributes.get("amount"),
34 | data_attributes.get("currency"),
35 | data_attributes.get("blockchain"),
36 | data_attributes.get("transaction_id"),
37 | data_attributes.get("address_to")
38 | )
39 |
--------------------------------------------------------------------------------
/src/community/feeds/feed_factory.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import src.enums
17 | import src.constants
18 | import src.community.feeds.community_ws_feed as community_ws_feed
19 | import src.community.feeds.community_mqtt_feed as community_mqtt_feed
20 | import src.community.feeds.community_supabase_feed as community_supabase_feed
21 |
22 |
23 | def community_feed_factory(authenticator, feed_type: src.enums.CommunityFeedType):
24 | feed_url = src.constants.COMMUNITY_FEED_URL
25 | if feed_type is src.enums.CommunityFeedType.WebsocketFeed:
26 | return community_ws_feed.CommunityWSFeed(feed_url, authenticator)
27 | if feed_type is src.enums.CommunityFeedType.MQTTFeed:
28 | return community_mqtt_feed.CommunityMQTTFeed(feed_url, authenticator)
29 | if feed_type is src.enums.CommunityFeedType.SupabaseFeed:
30 | return community_supabase_feed.CommunitySupabaseFeed(feed_url, authenticator)
31 | raise NotImplementedError(f"Unsupported feed type: {feed_type}")
32 |
--------------------------------------------------------------------------------
/static/img/stats_user.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/static/styles/style.less:
--------------------------------------------------------------------------------
1 | // compress:true
2 |
3 | @import "vars";
4 |
5 | @font-face {
6 | font-family: 'Cascadia Code PL Regular';
7 | src: url('../fonts/cascadia_code_pl_regular.eot'); /* IE 9 Compatibility Mode */
8 | src: url('../fonts/cascadia_code_pl_regular.eot?#iefix') format('embedded-opentype'), /* IE < 9 */
9 | url('../fonts/cascadia_code_pl_regular.woff2') format('woff2'), /* Super Modern Browsers */
10 | url('../fonts/cascadia_code_pl_regular.woff') format('woff'), /* Firefox >= 3.6, any other modern browser */
11 | url('../fonts/cascadia_code_pl_regular.ttf') format('truetype'), /* Safari, Android, iOS */
12 | url('../fonts/cascadia_code_pl_regular.svg#cascadia_code_pl_regular') format('svg'); /* Chrome < 4, Legacy iOS */
13 | }
14 |
15 | html {
16 | font-size: 15px;
17 | height: 100%;
18 | position: relative;
19 |
20 | @media @mobile-sm {
21 | min-height: none;
22 | }
23 | }
24 |
25 | body {
26 | margin: 0;
27 | font-size: 1rem;
28 | background: #10141D;
29 | color: @white;
30 | height: 100%;
31 | overflow: hidden;
32 | display: block;
33 | font-family: "Ubuntu", sans-serif;
34 | font-weight: 500;
35 | }
36 |
37 | main {
38 | display: flex;
39 | height: 100%;
40 | }
41 |
42 | .no-scroll {
43 | overflow: hidden;
44 | }
45 |
46 | *,
47 | *::before,
48 | *::after {
49 | box-sizing: border-box;
50 | -webkit-tap-highlight-color: transparent;
51 | }
52 |
53 | p {
54 | margin: 0 0 0.8rem;
55 | }
56 |
57 | h1,
58 | h2,
59 | h3,
60 | h4,
61 | h5,
62 | h6 {
63 | margin: 0;
64 | padding: 0;
65 | }
66 |
67 | // Blocks
68 |
69 | @import "blocks/container";
70 | @import "blocks/header";
71 | @import "blocks/modal";
72 | @import "blocks/left";
73 | @import "blocks/right";
74 | @import "blocks/center";
75 | @import "blocks/register";
76 | @import "blocks/profile";
--------------------------------------------------------------------------------
/src/community/models/community_fields.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import enum
17 |
18 |
19 | class CommunityFields(enum.Enum):
20 | ID = "_id"
21 | CURRENT_SESSION = "currentsession"
22 | STARTED_AT = "startedat"
23 | UP_TIME = "uptime"
24 | VERSION = "version"
25 | SIMULATOR = "simulator"
26 | TRADER = "trader"
27 | EVAL_CONFIG = "evalconfig"
28 | PAIRS = "pairs"
29 | EXCHANGES = "exchanges"
30 | EXCHANGE_TYPES = "exchangetypes"
31 | NOTIFICATIONS = "notifications"
32 | TYPE = "type"
33 | PLATFORM = "platform"
34 | REFERENCE_MARKET = "referencemarket"
35 | PORTFOLIO_VALUE = "portfoliovalue"
36 | PROFITABILITY = "profitability"
37 | TRADED_VOLUMES = "tradedvolumes"
38 | SUPPORTS = "supports"
39 | ROLES = "roles"
40 | DONATIONS = "donations"
41 | SIGNAL_EMITTER = "signalemitter"
42 | SIGNAL_RECEIVER = "signalreceiver"
43 | COMMUNITY_BOT_TYPE = "communitybottype"
44 | PROFILE_NAME = "profilename"
45 | PROFILE_ID = "profileid"
46 | PROFILE_IMPORTED = "profileimported"
47 |
--------------------------------------------------------------------------------
/static/img/sol_logo.svg:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/src/community/supabase_backend/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
3 | while# This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
4 |
5 |
6 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
7 | #
8 | # SniperCallsBot is free software; you can redistribute it and/or
9 | # modify it under the terms of the GNU General Public License
10 | # as published by the Free Software Foundation; either
11 | # version 3.0 of the License, or (at your option) any later version.
12 | #
13 | # SniperCallsBot is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 | # General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public
19 | # License along with SniperCallsBot. If not, see .
20 |
21 | from src.community.supabase_backend import postgres_functions
22 | from src.community.supabase_backend.postgres_functions import (
23 | PostgresFunctions,
24 | )
25 | from src.community.supabase_backend import configuration_storage
26 | from src.community.supabase_backend.configuration_storage import (
27 | SyncConfigurationStorage,
28 | ASyncConfigurationStorage,
29 | )
30 | from src.community.supabase_backend import supabase_client
31 | from src.community.supabase_backend.supabase_client import (
32 | AuthenticatedAsyncSupabaseClient,
33 | )
34 | from src.community.supabase_backend import community_supabase_client
35 | from src.community.supabase_backend.community_supabase_client import (
36 | CommunitySupabaseClient,
37 | HTTP_RETRY_COUNT,
38 | )
39 |
40 | __all__ = [
41 | "PostgresFunctions",
42 | "SyncConfigurationStorage",
43 | "ASyncConfigurationStorage",
44 | "AuthenticatedAsyncSupabaseClient",
45 | "CommunitySupabaseClient",
46 | "HTTP_RETRY_COUNT",
47 | ]
48 |
--------------------------------------------------------------------------------
/src/databases_util.py:
--------------------------------------------------------------------------------
1 | # Drakkar-Software SniperCallsBot-Trading
2 | # Copyright (c) Drakkar-Software, All rights reserved.
3 | #
4 | # This library is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU Lesser General Public
6 | # License as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # This library is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # Lesser General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU Lesser General Public
15 | # License along with this library
16 | import SniperCallsbot_trading.api as trading_api
17 | import SniperCallsbot_commons.databases as databases
18 | import SniperCallsbot_commons.optimization_campaign as optimization_campaign
19 | import SniperCallsbot_commons.constants as commons_constants
20 | import SniperCallsbot_commons.errors as commons_errors
21 |
22 |
23 | def get_run_databases_identifier(config, tentacles_setup_config, trading_mode_class=None, enable_storage=True):
24 | trading_mode = commons_constants.DEFAULT_STORAGE_TRADING_MODE
25 | try:
26 | trading_mode = trading_mode_class or trading_api.get_activated_trading_mode(tentacles_setup_config)
27 | except commons_errors.ConfigTradingError:
28 | # use default value
29 | pass
30 | return databases.RunDatabasesIdentifier(
31 | trading_mode,
32 | optimization_campaign.OptimizationCampaign.get_campaign_name(tentacles_setup_config),
33 | backtesting_id=config.get(commons_constants.CONFIG_BACKTESTING_ID),
34 | optimizer_id=config.get(commons_constants.CONFIG_OPTIMIZER_ID),
35 | live_id=trading_api.get_current_bot_live_id(config),
36 | enable_storage=enable_storage
37 | )
38 |
--------------------------------------------------------------------------------
/static/img/statistics.svg:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/src/community/models/community_supports.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import src.community.models.community_donation as community_donation
17 | import SniperCallsbot_commons.support as support
18 |
19 |
20 | class CommunitySupports(support.Support):
21 | DEFAULT_SUPPORT_ROLE = "default"
22 | SniperCallsBOT_DONOR_ROLE = "donor"
23 |
24 | def __init__(self, support_role: str = None, donations: list = None):
25 | self.support_role = support_role or CommunitySupports.DEFAULT_SUPPORT_ROLE
26 | self.donations = donations or []
27 |
28 | def is_supporting(self) -> bool:
29 | return self.support_role != self.DEFAULT_SUPPORT_ROLE or self.is_donor()
30 |
31 | def is_donor(self) -> bool:
32 | return self.support_role == self.SniperCallsBOT_DONOR_ROLE or bool(self.donations)
33 |
34 | @staticmethod
35 | def from_community_dict(data):
36 | return CommunitySupports(
37 | data["data"]["attributes"].get("support_role", CommunitySupports.DEFAULT_SUPPORT_ROLE),
38 | [community_donation.CommunityDonation.from_community_dict(donation_data)
39 | for donation_data in data.get("included", [])]
40 | )
41 |
--------------------------------------------------------------------------------
/static/img/profile.svg:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Coin Sniper Bot
2 |
3 | ## Overview
4 |
5 | **Coin Sniper Bot** is a state-of-the-art automated trading tool developed by **Solana experts**, specifically designed for meme coins. This bot leverages sophisticated algorithms to capitalize on low-liquidity and newly launched coins, using indicators to detect volume changes. **Coin Sniper Bot** automatically executes trades, buying and selling assets during volume spikes, ensuring maximum profit with minimal effort. Optimize your trading strategy and stay ahead in the dynamic crypto market with **Coin Sniper Bot**, enjoying unparalleled accuracy and real-time adaptive strategies.
6 |
7 | 
8 |
9 | ## Features
10 |
11 | - **Automated Trading**: Executes trades with precision and efficiency.
12 | - **Volume Detection**: Uses advanced indicators to detect changes in trading volume.
13 | - **Profit Maximization**: Buys and sells assets during volume spikes to maximize profits.
14 | - **Adaptive Strategies**: Adapts to market conditions in real-time.
15 | - **Ease of Use**: Integrates seamlessly into your trading workflow.
16 | - **Minimum rent**: The cheapest rent on the market.
17 |
18 | ## Installation
19 |
20 | **[👤 OUR TECHNICAL SUPPORT IN TELEGRAM!](https://t.me/mevsolana_help)**
21 |
22 | To get started with Coin Sniper Bot, follow these steps:
23 |
24 | 1. Clone the repository:
25 | ```sh
26 | git clone https://github.com/Green-EthanSOL/Sniper-Calls-Bot.git
27 | ```
28 |
29 | 2. Install the required dependencies:
30 | ```sh
31 | pip install -r requirements.txt
32 | ```
33 |
34 | ## Usage
35 |
36 | 1. Run the bot:
37 | ```sh
38 | python main.py
39 | ```
40 |
41 | ## Contributing
42 |
43 | We welcome contributions from the community! Please fork the repository and create a pull request with your changes. Ensure your code follows the project's coding standards and includes appropriate tests.
44 |
45 | ## License
46 |
47 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
--------------------------------------------------------------------------------
/static/register.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 |
18 |
19 |
44 |
45 | Coin Sniper Bot
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
Please wait, the bot is initializing
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_constraint.py:
--------------------------------------------------------------------------------
1 | # Drakkar-Software SniperCallsBot
2 | # Copyright (c) Drakkar-Software, All rights reserved.
3 | #
4 | # This library is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU Lesser General Public
6 | # License as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # This library is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # Lesser General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU Lesser General Public
15 | # License along with this library.
16 |
17 |
18 | class OptimizerConstraint:
19 | NAME_KEY = "name"
20 | MIN_VAL_KEY = "min_val"
21 | MAX_VAL_KEY = "max_val"
22 | MIN_STEP_KEY = "min_step"
23 | MAX_STEP_KEY = "max_step"
24 | STAY_WITHIN_BOUNDARIES_KEY = "stay_within_boundaries"
25 |
26 | def __init__(self, name, min_val, max_val, min_step, max_step, stay_within_boundaries):
27 | self.name = name
28 | self.min_val = min_val
29 | self.max_val = max_val
30 | self.min_step = min_step
31 | self.max_step = max_step
32 | self.stay_within_boundaries = stay_within_boundaries
33 |
34 | def is_min_max_valid(self, value):
35 | if self.max_val is not None and not value > self.max_val:
36 | return False
37 | if self.min_val is not None and not value < self.min_val:
38 | return False
39 | return True
40 |
41 | @classmethod
42 | def from_dict(cls, param_dict):
43 | return cls(
44 | param_dict.get(cls.NAME_KEY),
45 | param_dict.get(cls.MIN_VAL_KEY),
46 | param_dict.get(cls.MAX_VAL_KEY),
47 | param_dict.get(cls.MIN_STEP_KEY),
48 | param_dict.get(cls.MAX_STEP_KEY),
49 | param_dict.get(cls.STAY_WITHIN_BOUNDARIES_KEY),
50 | )
51 |
--------------------------------------------------------------------------------
/src/automation/bases/abstract_trigger_event.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import abc
17 | import time
18 |
19 | import src.automation.bases.automation_step as automation_step
20 |
21 |
22 | class AbstractTriggerEvent(automation_step.AutomationStep, abc.ABC):
23 | def __init__(self):
24 | super(AbstractTriggerEvent, self).__init__()
25 | self.should_stop = False
26 | self.trigger_only_once = False
27 | self.max_trigger_frequency = 0
28 | self._last_trigger_time = 0
29 |
30 | async def stop(self):
31 | self.should_stop = True
32 |
33 | async def _get_next_event(self):
34 | raise NotImplementedError
35 |
36 | async def next_event(self):
37 | """
38 | Async generator, use as follows:
39 | async for event in self.next_event():
40 | # triggered when an event occurs
41 | """
42 | self._last_trigger_time = 0
43 | while not self.should_stop and not (self.trigger_only_once and self._last_trigger_time != 0):
44 | new_event = await self._get_next_event()
45 | trigger_time = time.time()
46 | if not self.max_trigger_frequency or (trigger_time - self._last_trigger_time > self.max_trigger_frequency):
47 | yield new_event
48 | self._last_trigger_time = time.time()
49 |
--------------------------------------------------------------------------------
/src/community/errors_upload/initializer.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import time
17 |
18 | import src.community.errors_upload.errors_uploader as errors_uploader
19 | import src.community.errors_upload.error_model as error_model
20 | import SniperCallsbot_commons.logging as logging
21 | import src.constants as constants
22 |
23 |
24 | class _UploadWrapper:
25 | def __init__(self, upload_url, config):
26 | self._config = config
27 | self._metrics_id = self._get_metrics_id()
28 | self._uploader = errors_uploader.ErrorsUploader(
29 | upload_url
30 | )
31 |
32 | def upload_if_necessary(self, exception, error_message):
33 | if constants.UPLOAD_ERRORS and (constants.IS_CLOUD_ENV or self._config.get_metrics_enabled()):
34 | self._uploader.schedule_error_upload(
35 | error_model.Error(
36 | exception, error_message, time.time(), self._metrics_id
37 | )
38 | )
39 |
40 | def _get_metrics_id(self):
41 | try:
42 | return self._config.get_metrics_id()
43 | except KeyError:
44 | return constants.DEFAULT_METRICS_ID
45 |
46 |
47 | def register_error_uploader(upload_url, config):
48 | upload_wrapper = _UploadWrapper(upload_url, config)
49 | logging.BotLogger.register_error_callback(upload_wrapper.upload_if_necessary)
50 |
--------------------------------------------------------------------------------
/static/img/another_crypto.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 | *.orig
6 |
7 | # C extensions
8 | *.so
9 |
10 | # Distribution / packaging
11 | .Python
12 | .pytest_cache/
13 | env/
14 | build/
15 | develop-eggs/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | # *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .coverage
43 | .coverage.*
44 | .cache
45 | nosetests.xml
46 | coverage.xml
47 | *.cover
48 | .hypothesis/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 |
58 | # Flask stuff:
59 | instance/
60 | .webassets-cache
61 |
62 | # Scrapy stuff:
63 | .scrapy
64 |
65 | # Sphinx documentation
66 | docs/_build/
67 |
68 | # PyBuilder
69 | target/
70 |
71 | # Jupyter Notebook
72 | .ipynb_checkpoints
73 |
74 | # pyenv
75 | .python-version
76 |
77 | # celery beat schedule file
78 | celerybeat-schedule
79 |
80 | # SageMath parsed files
81 | *.sage.py
82 |
83 | # virtualenv
84 | .venv
85 | venv/
86 | ENV/
87 |
88 | # Spyder project settings
89 | .spyderproject
90 | .spyproject
91 |
92 | # Rope project settings
93 | .ropeproject
94 |
95 | # mkdocs documentation
96 | /site
97 |
98 | # mypy
99 | .mypy_cache/
100 |
101 | # IDE
102 | .vscode/
103 | .idea
104 | .gitpod.yml
105 |
106 | # Tentacles manager temporary files
107 | SniperCallsbot/creator_temp/
108 | creator_temp/
109 |
110 | # Data
111 | backtesting/collector/data/
112 | backtesting/data/
113 |
114 | # Tentacles
115 | tentacles
116 | downloaded_temp_tentacles
117 |
118 | # User config
119 | user/
120 | temp_config.json
121 |
122 | *.csv
123 | *.ods
124 | *.c
125 | *.h
126 |
127 | # SniperCallsBot logs
128 | logs
129 |
130 | # Debug
131 | cython_debug/
132 |
133 | # dev env
134 | .env
135 |
--------------------------------------------------------------------------------
/src/community/models/community_public_data.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import dataclasses
17 | import src.community.supabase_backend.enums as enums
18 | import src.community.models.strategy_data as strategy_data
19 |
20 |
21 | class CommunityPublicData:
22 | def __init__(self):
23 | self.products = _DataElement({}, False)
24 |
25 | def set_products(self, products):
26 | self.products.value = {product[enums.ProductKeys.ID.value]: product for product in products}
27 | self.products.fetched = True
28 |
29 | def get_product_slug(self, product_id):
30 | return self.products.value[product_id][enums.ProductKeys.SLUG.value]
31 |
32 | def get_strategies(self, strategy_categories) -> list[strategy_data.StrategyData]:
33 | return [
34 | strategy_data.StrategyData.from_dict(strategy_dict)
35 | for strategy_dict in self.products.value.values()
36 | if self._get_category_type(strategy_dict) in strategy_categories
37 | ]
38 |
39 | def _get_category_type(self, product: dict):
40 | category = product.get("category") or {}
41 | return category.get("type")
42 |
43 | def get_strategy(self, strategy_id: str) -> strategy_data.StrategyData:
44 | return strategy_data.StrategyData.from_dict(self.products.value[strategy_id])
45 |
46 |
47 | @dataclasses.dataclass
48 | class _DataElement:
49 | value: any
50 | fetched: bool
51 |
--------------------------------------------------------------------------------
/static/img/usdterc20_5ae21618aa.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/static/img/settings.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/static/img/usdtbsc_b8f3d8f316.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/community/feeds/abstract_feed.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import time
17 |
18 | import SniperCallsbot_commons.logging as bot_logging
19 |
20 |
21 | class AbstractFeed:
22 | def __init__(self, feed_url, authenticator):
23 | self.logger: bot_logging.BotLogger = bot_logging.get_logger(
24 | self.__class__.__name__
25 | )
26 | self.feed_url = feed_url
27 | self.should_stop = False
28 | self.authenticator = authenticator
29 | self.feed_callbacks = {}
30 | self.subscribed = False
31 | self.last_message_time = None
32 | self.is_signal_receiver = False
33 | self.is_signal_emitter = False
34 |
35 | def has_registered_feed(self) -> bool:
36 | return bool(self.feed_callbacks)
37 |
38 | async def start(self):
39 | raise NotImplementedError("start is not implemented")
40 |
41 | async def stop(self):
42 | raise NotImplementedError("stop is not implemented")
43 |
44 | async def register_feed_callback(self, channel_type, callback, identifier=None):
45 | raise NotImplementedError("register_feed_callback is not implemented")
46 |
47 | async def send(self, message, channel_type, identifier, **kwargs):
48 | raise NotImplementedError("send is not implemented")
49 |
50 | def can_connect(self):
51 | return True
52 |
53 | def is_connected_to_remote_feed(self):
54 | return False
55 |
56 | def update_last_message_time(self):
57 | self.last_message_time = time.time()
58 |
59 | def is_up_to_date_with_account(self, user_account):
60 | return True
61 |
62 | def is_connected(self):
63 | return False
64 |
--------------------------------------------------------------------------------
/src/strategy_optimizer/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.strategy_optimizer import test_suite_result
18 | from src.strategy_optimizer import strategy_optimizer
19 | from src.strategy_optimizer import strategy_design_optimizer
20 | from src.strategy_optimizer import strategy_test_suite
21 |
22 | from src.strategy_optimizer.test_suite_result import (
23 | TestSuiteResult,
24 | TestSuiteResultSummary,
25 | )
26 | from src.strategy_optimizer.strategy_optimizer import (
27 | StrategyOptimizer,
28 | )
29 | from src.strategy_optimizer.fitness_parameter import (
30 | FitnessParameter,
31 | )
32 | from src.strategy_optimizer.optimizer_filter import (
33 | OptimizerFilter,
34 | )
35 | from src.strategy_optimizer.optimizer_settings import (
36 | OptimizerSettings,
37 | )
38 | from src.strategy_optimizer.scored_run_result import (
39 | ScoredRunResult,
40 | )
41 | from src.strategy_optimizer.optimizer_constraint import (
42 | OptimizerConstraint,
43 | )
44 | from src.strategy_optimizer.strategy_design_optimizer import (
45 | StrategyDesignOptimizer,
46 | )
47 | from src.strategy_optimizer.strategy_test_suite import (
48 | StrategyTestSuite,
49 | )
50 | from src.strategy_optimizer.strategy_design_optimizer_factory import (
51 | create_most_advanced_strategy_design_optimizer,
52 | )
53 |
54 | __all__ = [
55 | "TestSuiteResult",
56 | "TestSuiteResultSummary",
57 | "StrategyOptimizer",
58 | "FitnessParameter",
59 | "OptimizerFilter",
60 | "OptimizerSettings",
61 | "ScoredRunResult",
62 | "OptimizerConstraint",
63 | "StrategyDesignOptimizer",
64 | "StrategyTestSuite",
65 | "create_most_advanced_strategy_design_optimizer",
66 | ]
67 |
--------------------------------------------------------------------------------
/static/img/swipe.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/strategy_optimizer/scored_run_result.py:
--------------------------------------------------------------------------------
1 | # Drakkar-Software SniperCallsBot
2 | # Copyright (c) Drakkar-Software, All rights reserved.
3 | #
4 | # This library is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU Lesser General Public
6 | # License as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # This library is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # Lesser General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU Lesser General Public
15 | # License along with this library.
16 |
17 |
18 | class ScoredRunResult:
19 | def __init__(self, full_result, optimizer_run_data):
20 | self.full_result = full_result
21 | self.optimizer_run_data = optimizer_run_data
22 | self.values = {}
23 | self.score = 0
24 | self.total_weight = 0
25 |
26 | def compute_score(self, relevant_scoring_parameters):
27 | self.score = 0
28 | try:
29 | self.score = sum([
30 | self._compute_score(scoring_parameter)
31 | for scoring_parameter in relevant_scoring_parameters
32 | ]) / self.total_weight
33 | except ZeroDivisionError:
34 | self.score = 0
35 |
36 | def _compute_score(self, fitness_parameter):
37 | try:
38 | self.values[fitness_parameter.name] = self.full_result[fitness_parameter.name]
39 | score = fitness_parameter.get_normalized_value(self.values[fitness_parameter.name])
40 | self.total_weight += fitness_parameter.weight
41 | return score
42 | except KeyError:
43 | return 0
44 |
45 | def __repr__(self):
46 | return f"[{self.__class__.__name__}] score: {self.score}, total_weight: {self.total_weight}"
47 |
48 | def result_str(self):
49 | # todo move constants outside of StrategyDesignOptimizer
50 | import src.strategy_optimizer.strategy_design_optimizer as strategy_design_optimizer
51 | user_inputs = {
52 | ui[strategy_design_optimizer.StrategyDesignOptimizer.CONFIG_USER_INPUT]:
53 | ui[strategy_design_optimizer.StrategyDesignOptimizer.CONFIG_VALUE]
54 | for ui in self.optimizer_run_data
55 | }
56 | return f"fitness score: {self.score} {self.values} from {user_inputs}"
57 |
--------------------------------------------------------------------------------
/src/strategy_optimizer/fitness_parameter.py:
--------------------------------------------------------------------------------
1 | # Drakkar-Software SniperCallsBot
2 | # Copyright (c) Drakkar-Software, All rights reserved.
3 | #
4 | # This library is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU Lesser General Public
6 | # License as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # This library is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # Lesser General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU Lesser General Public
15 | # License along with this library.
16 |
17 |
18 | class FitnessParameter:
19 | NAME_KEY = "name"
20 | WEIGHT_KEY = "weight"
21 | IS_RATIO_FROM_MAX_KEY = "is_ratio_from_max"
22 |
23 | def __init__(self, name, weight, is_ratio_from_max):
24 | self.name = name
25 | self.weight = weight
26 | self.is_ratio_from_max = is_ratio_from_max
27 | self.max_ratio_value = None
28 | self.min_ratio_value = None
29 |
30 | def get_normalized_value(self, raw_value):
31 | if self.is_ratio_from_max:
32 | # use ratio if relevant
33 | return self._get_value_from_ratio(raw_value) * self.weight
34 | return raw_value * self._get_parameter_normalizer() * self.weight
35 |
36 | def _get_value_from_ratio(self, raw_value):
37 | return (
38 | raw_value * self._get_parameter_normalizer() if self.max_ratio_value is None
39 | else (raw_value - self.min_ratio_value) / (self.max_ratio_value - self.min_ratio_value)
40 | )
41 |
42 | def _get_parameter_normalizer(self):
43 | return 0.01 if "%" in self.name else 1
44 |
45 | def update_ratio(self, full_result):
46 | try:
47 | if self.max_ratio_value is None or full_result[self.name] > self.max_ratio_value:
48 | self.max_ratio_value = full_result[self.name]
49 | if self.min_ratio_value is None or full_result[self.name] < self.min_ratio_value:
50 | self.min_ratio_value = full_result[self.name]
51 | except KeyError:
52 | pass
53 |
54 | @classmethod
55 | def from_dict(cls, param_dict):
56 | return cls(
57 | param_dict[cls.NAME_KEY],
58 | param_dict[cls.WEIGHT_KEY],
59 | param_dict[cls.IS_RATIO_FROM_MAX_KEY],
60 | )
61 |
--------------------------------------------------------------------------------
/src/community/models/__init__.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 |
17 | from src.community.models import community_user_account
18 | from src.community.models.community_user_account import (
19 | CommunityUserAccount,
20 | )
21 | from src.community.models import community_fields
22 | from src.community.models.community_fields import (
23 | CommunityFields,
24 | )
25 |
26 | from src.community.models import community_tentacles_package
27 | from src.community.models import community_supports
28 | from src.community.models import community_donation
29 | from src.community.models import startup_info
30 |
31 | from src.community.models.community_tentacles_package import (
32 | CommunityTentaclesPackage
33 | )
34 | from src.community.models.community_supports import (
35 | CommunitySupports
36 | )
37 | from src.community.models.community_donation import (
38 | CommunityDonation
39 | )
40 | from src.community.models.startup_info import (
41 | StartupInfo
42 | )
43 | from src.community.models.formatters import (
44 | format_trades,
45 | format_orders,
46 | format_portfolio,
47 | format_portfolio_history,
48 | format_portfolio_with_profitability,
49 | )
50 | from src.community.models.community_public_data import (
51 | CommunityPublicData
52 | )
53 | from src.community.models.strategy_data import (
54 | StrategyData
55 | )
56 |
57 | __all__ = [
58 | "CommunityUserAccount",
59 | "CommunityFields",
60 | "CommunityTentaclesPackage",
61 | "CommunitySupports",
62 | "CommunityDonation",
63 | "StartupInfo",
64 | "format_trades",
65 | "format_orders",
66 | "format_portfolio",
67 | "format_portfolio_history",
68 | "format_portfolio_with_profitability",
69 | "CommunityPublicData",
70 | "StrategyData",
71 | ]
72 |
--------------------------------------------------------------------------------
/static/img/matic_token_f9906e3f5d.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | from setuptools import find_packages
17 | from setuptools import setup
18 | from src import PROJECT_NAME, AUTHOR, VERSION
19 |
20 | PACKAGES = find_packages(exclude=["tentacles*", "tests", ])
21 |
22 | # long description from README file
23 | with open('README.md', encoding='utf-8') as f:
24 | DESCRIPTION = f.read()
25 |
26 |
27 | def ignore_git_requirements(requirements):
28 | return [requirement for requirement in requirements if "git+" not in requirement]
29 |
30 |
31 | REQUIRED = ignore_git_requirements(open('requirements.txt').readlines())
32 | REQUIRES_PYTHON = '>=3.10'
33 |
34 | setup(
35 | name=PROJECT_NAME,
36 | version=VERSION,
37 | url='https://github.com/Drakkar-Software/SniperCallsBot',
38 | license='GPL-3.0',
39 | author=AUTHOR,
40 | author_email='contact@drakkar.software',
41 | description='Cryptocurrencies alert / trading bot',
42 | py_modules=['start'],
43 | packages=PACKAGES,
44 | package_data={
45 | "": ["config/*", "strategy_optimizer/optimizer_data_files/*"],
46 | },
47 | long_description=DESCRIPTION,
48 | long_description_content_type='text/markdown',
49 | tests_require=["pytest"],
50 | test_suite="tests",
51 | zip_safe=False,
52 | install_requires=REQUIRED,
53 | python_requires=REQUIRES_PYTHON,
54 | entry_points={
55 | 'console_scripts': [
56 | PROJECT_NAME + ' = SniperCallsbot.cli:main'
57 | ]
58 | },
59 | classifiers=[
60 | 'Development Status :: 4 - Beta',
61 | 'Operating System :: OS Independent',
62 | 'Operating System :: MacOS :: MacOS X',
63 | 'Operating System :: Microsoft :: Windows',
64 | 'Operating System :: POSIX',
65 | 'Programming Language :: Python :: 3.10',
66 | ],
67 | )
68 |
--------------------------------------------------------------------------------
/static/img/usdttrc20_87164a7b35.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/enums.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import enum
17 |
18 |
19 | class CommunityFeedType(enum.Enum):
20 | WebsocketFeed = "WebsocketFeed"
21 | MQTTFeed = "MQTTFeed"
22 | SupabaseFeed = "SupabaseFeed"
23 |
24 |
25 | class CommunityEnvironments(enum.Enum):
26 | Staging = "Staging"
27 | Production = "Production"
28 |
29 |
30 | class OptimizerModes(enum.Enum):
31 | NORMAL = "normal"
32 | GENETIC = "genetic"
33 |
34 |
35 | class OptimizerConfig(enum.Enum):
36 | OPTIMIZER_ID = "optimizer_id"
37 | OPTIMIZER_IDS = "optimizer_ids"
38 | RANDOMLY_CHOSE_RUNS = "randomly_chose_runs"
39 | DATA_FILES = "data_files"
40 | OPTIMIZER_CONFIG = "optimizer_config"
41 | EXCHANGE_TYPE = "exchange_type"
42 | QUEUE_SIZE = "queue_size"
43 | EMPTY_THE_QUEUE = "empty_the_queue"
44 | START_TIMESTAMP = "start_timestamp"
45 | END_TIMESTAMP = "end_timestamp"
46 | IDLE_CORES = "idle_cores"
47 | NOTIFY_WHEN_COMPLETE = "notify_when_complete"
48 | DB_UPDATE_PERIOD = "db_update_period"
49 | MODE = "mode"
50 | MAX_OPTIMIZER_RUNS = "max_optimizer_runs"
51 | INITIAL_GENERATION_COUNT = "initial_generation_count"
52 | DEFAULT_GENERATIONS_COUNT = "default_generations_count"
53 | DEFAULT_RUN_PER_GENERATION = "default_run_per_generation"
54 | DEFAULT_SCORING_PARAMETERS = "default_scoring_parameters"
55 | DEFAULT_OPTIMIZER_FILTERS = "default_optimizer_filters"
56 | DEFAULT_OPTIMIZER_CONSTRAINTS = "default_optimizer_constraints"
57 | DEFAULT_MUTATION_PERCENT = "default_mutation_percent"
58 | MAX_MUTATION_PROBABILITY_PERCENT = "max_mutation_probability_percent"
59 | MIN_MUTATION_PROBABILITY_PERCENT = "min_mutation_probability_percent"
60 | DEFAULT_MAX_MUTATION_NUMBER_MULTIPLIER = "default_max_mutation_number_multiplier"
61 | DEFAULT_CROSSOVER_PERCENT = "default_crossover_percent"
62 | STAY_WITHIN_BOUNDARIES = "stay_within_boundaries"
63 | TARGET_FITNESS_SCORE = "target_fitness_score"
64 |
--------------------------------------------------------------------------------
/static/img/usdcerc20_acd5759c8c.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/community/errors_upload/error_model.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import traceback
17 |
18 |
19 | class Error:
20 | """
21 | Error is the error data wrapper use to upload errors to the error server
22 | """
23 |
24 | def __init__(self, error: Exception, title: str, timestamp: float, metrics_id: str):
25 | self.error: Exception = error
26 | self.title: str = str(title)
27 | self.first_timestamp: float = timestamp
28 | self.last_timestamp: float = timestamp
29 | self.count: int = 1
30 | self.metrics_id: str = metrics_id
31 | self.type: str = self.error.__class__.__name__ if self.error else ""
32 | self.stacktrace: list = traceback.format_exception(
33 | type(self.error), value=self.error, tb=self.error.__traceback__
34 | )[1:] if self.error and isinstance(self.error, Exception) else []
35 |
36 | def to_dict(self) -> dict:
37 | """
38 | Return the dict serialization of self
39 | """
40 | return {
41 | "title": self.title,
42 | "type": self.type,
43 | "stacktrace": self.stacktrace,
44 | "firsttimestamp": self.first_timestamp,
45 | "lasttimestamp": self.last_timestamp,
46 | "count": self.count,
47 | "metricsid": self.metrics_id,
48 | }
49 |
50 | def is_equivalent(self, other) -> bool:
51 | return (self.error is other.error or
52 | (type(self.error) is type(other.error)
53 | and self.error.args == other.error.args)) and \
54 | self.title == other.title and \
55 | self.metrics_id == other.metrics_id and \
56 | self.type == other.type and \
57 | self.stacktrace == other.stacktrace
58 |
59 | def merge_equivalent(self, other):
60 | self.count += other.count
61 | if other.last_timestamp > self.last_timestamp:
62 | self.last_timestamp = other.last_timestamp
63 |
--------------------------------------------------------------------------------
/src/initializer.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import SniperCallsbot_tentacles_manager.api as tentacles_manager_api
17 | import src.constants as constants
18 | import SniperCallsbot_commons.databases as databases
19 | import SniperCallsbot_commons.logging as logging
20 | import SniperCallsbot_commons.errors as commons_errors
21 | import src.databases_util as databases_util
22 |
23 |
24 | class Initializer:
25 | """Initializer class:
26 | - Initialize services, constants and tools
27 | """
28 |
29 | def __init__(self, SniperCallsbot):
30 | self.SniperCallsbot = SniperCallsbot
31 |
32 | async def create(self, init_bot_storage):
33 | # initialize tentacle configuration
34 | tentacles_config_path = self.SniperCallsbot.get_startup_config(constants.CONFIG_KEY, dict_only=False).\
35 | get_tentacles_config_path()
36 | self.SniperCallsbot.tentacles_setup_config = tentacles_manager_api.get_tentacles_setup_config(tentacles_config_path)
37 |
38 | if init_bot_storage:
39 | try:
40 | # init bot storage
41 | await databases.init_bot_storage(
42 | self.SniperCallsbot.bot_id,
43 | databases_util.get_run_databases_identifier(
44 | self.SniperCallsbot.config,
45 | self.SniperCallsbot.tentacles_setup_config
46 | ),
47 | True
48 | )
49 | except commons_errors.ConfigTradingError as err:
50 | # already logged as error, don't display it twice
51 | logging.get_logger(self.__class__.__name__).warning(f"Error when initializing bot storage: {err}")
52 | except Exception as err:
53 | logging.get_logger(self.__class__.__name__).exception(
54 | err, True, f"Error when initializing bot storage: {err}"
55 | )
56 |
57 | # create SniperCallsBot channel
58 | await self.SniperCallsbot.global_consumer.initialize()
59 |
--------------------------------------------------------------------------------
/static/img/working_bot.svg:
--------------------------------------------------------------------------------
1 |
46 |
--------------------------------------------------------------------------------
/src/updater/updater.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import packaging.version as packaging_version
17 |
18 | import src.constants as constants
19 | import src.configuration_manager as configuration_manager
20 | import src.commands as commands
21 | import SniperCallsbot_commons.logging as logging
22 | import SniperCallsbot_commons.authentication as authentication
23 |
24 |
25 | class Updater:
26 | def __init__(self):
27 | self.logger = logging.get_logger(self.__class__.__name__)
28 |
29 | async def should_be_updated(self):
30 | """
31 | :return: True if the updater version is greater than current bot version
32 | """
33 | try:
34 | latest_version = await self.get_latest_version()
35 | if latest_version is None:
36 | return False
37 | return packaging_version.parse(latest_version) > packaging_version.parse(constants.VERSION)
38 | except TypeError as e:
39 | self.logger.debug(f"Error when comparing latest with current SniperCallsBot version: {e}")
40 |
41 | async def get_latest_version(self):
42 | raise NotImplementedError("get_latest_version is not implemented")
43 |
44 | async def update_impl(self) -> bool:
45 | raise NotImplementedError("update_impl is not implemented")
46 |
47 | async def update_tentacles(self):
48 | authenticator = authentication.Authenticator.instance()
49 | additional_tentacles_package_urls = authenticator.get_saved_package_urls()
50 | await commands.install_all_tentacles(
51 | tentacles_url=configuration_manager.get_default_tentacles_url(version=await self.get_latest_version()),
52 | additional_tentacles_package_urls=additional_tentacles_package_urls
53 | )
54 |
55 | async def post_update(self):
56 | await self.update_tentacles()
57 | commands.restart_bot()
58 |
59 | async def update(self):
60 | """
61 | Call updater update_impl and updates tentacles on update success
62 | """
63 | if await self.update_impl():
64 | await self.post_update()
65 |
--------------------------------------------------------------------------------
/static/img/logo_white.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/static/img/logo_gray.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/config/config_schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "properties": {
4 | "DEBUG": {
5 | "type": "boolean"
6 | },
7 | "DEV-MODE": {
8 | "type": "boolean"
9 | },
10 | "SAVE_EVALUATIONS": {
11 | "type": "boolean"
12 | },
13 | "accepted_terms": {
14 | "type": "boolean"
15 | },
16 | "profile": {
17 | "type": "string"
18 | },
19 | "community": {
20 | "type": "object",
21 | "properties": {
22 | "bot_id": {
23 | "type": "string"
24 | },
25 | "supabase.auth.token": {
26 | "type": "string"
27 | },
28 | "environment": {
29 | "type": "string"
30 | }
31 | }
32 | },
33 | "backtesting": {
34 | "type": "object",
35 | "properties": {
36 | "files": {
37 | "type": "array",
38 | "items": {
39 | "type": "string"
40 | }
41 | }
42 | }
43 | },
44 | "data-collector": {
45 | "type": "object",
46 | "properties": {
47 | "symbol": {
48 | "type": "string"
49 | }
50 | }
51 | },
52 | "exchanges": {
53 | "type": "object",
54 | "patternProperties": {
55 | "^.*$": {
56 | "type": "object"
57 | }
58 | }
59 | },
60 | "metrics": {
61 | "type": "object",
62 | "properties": {
63 | "enabled": {
64 | "type": "boolean"
65 | },
66 | "metrics-bot-id": {
67 | "type": "string"
68 | }
69 | }
70 | },
71 | "community-token": {
72 | "type": "string"
73 | },
74 | "notification": {
75 | "type": "object",
76 | "properties": {
77 | "global-info": {
78 | "type": "boolean"
79 | },
80 | "price-alerts": {
81 | "type": "boolean"
82 | },
83 | "trades": {
84 | "type": "boolean"
85 | },
86 | "other": {
87 | "type": "boolean"
88 | },
89 | "notification-type": {
90 | "type": "array",
91 | "items": {
92 | "type": "string"
93 | }
94 | }
95 | },
96 | "required": [
97 | "global-info",
98 | "price-alerts",
99 | "trades",
100 | "notification-type"
101 | ]
102 | },
103 | "services": {
104 | "type": "object",
105 | "patternProperties": {
106 | "^.*$": {
107 | "type": "object"
108 | }
109 | }
110 | },
111 | "watched_symbols": {
112 | "type": "array",
113 | "items": {
114 | "type": "string"
115 | }
116 | }
117 | },
118 | "required": [
119 | "backtesting",
120 | "exchanges",
121 | "services",
122 | "notification"
123 | ],
124 | "additionalProperties": {
125 | "type": "string"
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.10-slim-buster AS base
2 |
3 | WORKDIR /
4 |
5 | # requires git to install requirements with git+https
6 | RUN apt-get update \
7 | && apt-get install -y --no-install-recommends build-essential git gcc binutils libffi-dev libssl-dev libxml2-dev libxslt1-dev libxslt-dev libjpeg62-turbo-dev zlib1g-dev \
8 | && python -m venv /opt/venv
9 |
10 | # skip cryptography rust compilation (required for armv7 builds)
11 | ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1
12 |
13 | # Make sure we use the virtualenv:
14 | ENV PATH="/opt/venv/bin:$PATH"
15 |
16 | COPY . .
17 | RUN pip install -U setuptools wheel pip>=20.0.0 \
18 | && pip install --no-cache-dir --prefer-binary -r requirements.txt \
19 | && python setup.py install
20 |
21 | # build amazon-efs-utils
22 | # use v1.36.0 to avoid rust compiler requirement
23 | WORKDIR /opt/efs
24 | RUN git clone https://github.com/aws/efs-utils --branch v1.36.0 . \
25 | && ./build-deb.sh
26 |
27 | FROM python:3.10-slim-buster
28 |
29 | ARG TENTACLES_URL_TAG=""
30 | ENV TENTACLES_URL_TAG=$TENTACLES_URL_TAG
31 |
32 | WORKDIR /SniperCallsbot
33 |
34 | # Import python dependencies
35 | COPY --from=base /opt/venv /opt/venv
36 |
37 | # Import built dependencies
38 | COPY --from=base /opt/efs/build /opt/efs/build
39 |
40 | # Add default config files
41 | COPY SniperCallsbot/config /SniperCallsbot/SniperCallsbot/config
42 |
43 | COPY docker/* /SniperCallsbot/
44 |
45 | # 1. Install requirements
46 | # 2. Add cloudflare gpg key and add cloudflare repo in apt repositories (from https://pkg.cloudflare.com/index.html)
47 | # 3. Install required packages
48 | # 4. Finish env setup
49 | SHELL ["/bin/bash", "-o", "pipefail", "-c"]
50 | RUN apt-get update \
51 | && apt-get install -y --no-install-recommends curl \
52 | && mkdir -p /usr/share/keyrings \
53 | && chmod 0755 /usr/share/keyrings \
54 | && curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null \
55 | && echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared buster main' | tee /etc/apt/sources.list.d/cloudflared.list \
56 | && apt-get update \
57 | && apt-get install -y --no-install-recommends curl cloudflared s3fs nfs-common libxslt-dev libxcb-xinput0 libjpeg62-turbo-dev zlib1g-dev libblas-dev liblapack-dev libatlas-base-dev libopenjp2-7 libtiff-dev \
58 | && apt-get -y install --no-install-recommends /opt/efs/build/amazon-efs-utils*deb \
59 | && rm -rf /opt/efs \
60 | && rm -rf /var/lib/apt/lists/* \
61 | && ln -s /opt/venv/bin/SniperCallsBot SniperCallsBot # Make sure we use the virtualenv \
62 | && chmod +x docker-entrypoint.sh
63 |
64 | VOLUME /SniperCallsbot/backtesting
65 | VOLUME /SniperCallsbot/logs
66 | VOLUME /SniperCallsbot/tentacles
67 | VOLUME /SniperCallsbot/user
68 |
69 | EXPOSE 5001
70 |
71 | HEALTHCHECK --interval=15s --timeout=10s --retries=5 CMD curl -sS http://127.0.0.1:5001 || exit 1
72 |
73 | ENTRYPOINT ["./docker-entrypoint.sh"]
74 |
--------------------------------------------------------------------------------
/src/community/models/community_tentacles_package.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import typing
17 | import packaging.version
18 |
19 | import src.community.identifiers_provider as identifiers_provider
20 | import src.constants as constants
21 |
22 |
23 | class CommunityTentaclesPackage:
24 | def __init__(self, name, description, url, activated, images, download_url, versions, last_version):
25 | self.name: str = name
26 | self.description: str = description
27 | self.url: str = url
28 | self.activated: bool = activated
29 | self.images: typing.List[str] = images
30 | self.download_url: str = download_url
31 | self.uninstalled: bool = not self.is_installed()
32 | self.versions: typing.List[str] = versions
33 | self.last_version: str = last_version
34 |
35 | @staticmethod
36 | def from_community_dict(data):
37 | data_attributes = data["attributes"]
38 | # todo update with new urls
39 | return CommunityTentaclesPackage(
40 | data_attributes.get("name"),
41 | data_attributes.get("description"),
42 | f"{identifiers_provider.IdentifiersProvider.COMMUNITY_URL}products/{data_attributes.get('product_slug')}",
43 | data_attributes.get("activated"),
44 | data["relationships"].get('images')['data'],
45 | f"{identifiers_provider.IdentifiersProvider.COMMUNITY_URL}{data_attributes.get('download_path')}",
46 | data_attributes.get("versions"),
47 | data_attributes.get("last_version")
48 | )
49 |
50 | def get_latest_compatible_version(self):
51 | current_bot_version = packaging.version.parse(constants.LONG_VERSION)
52 | if packaging.version.parse(self.last_version) <= current_bot_version:
53 | return self.last_version
54 | available_versions = sorted([packaging.version.parse(version) for version in self.versions], reverse=True)
55 | for version in available_versions:
56 | if version <= current_bot_version:
57 | return version
58 | return None
59 |
60 | def is_installed(self):
61 | #TODO tmp
62 | import random
63 | return random.choice((True, False))
64 |
--------------------------------------------------------------------------------
/src/strategy_optimizer/optimizer_filter.py:
--------------------------------------------------------------------------------
1 | # Drakkar-Software SniperCallsBot
2 | # Copyright (c) Drakkar-Software, All rights reserved.
3 | #
4 | # This library is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU Lesser General Public
6 | # License as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # This library is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # Lesser General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU Lesser General Public
15 | # License along with this library.
16 | import decimal
17 | import SniperCallsbot_commons.logical_operators as logical_operators
18 |
19 |
20 | class OptimizerFilter:
21 | LEFT_OPERAND_KEY_KEY = "left_operand_key"
22 | RIGHT_OPERAND_KEY_KEY = "right_operand_key"
23 | LEFT_OPERAND_VALUE_KEY = "left_operand_value"
24 | RIGHT_OPERAND_VALUE_KEY = "right_operand_value"
25 | OPERATOR_KEY = "operator"
26 |
27 | def __init__(self, left_operand_key, right_operand_key, left_operand_value, right_operand_value, operator):
28 | self.left_operand_key = left_operand_key
29 | self.right_operand_key = right_operand_key
30 | self.left_operand_value = left_operand_value
31 | self.right_operand_value = right_operand_value
32 | self.operator = operator
33 |
34 | def is_valid(self):
35 | return self.left_operand_value and self.right_operand_value and self.operator
36 |
37 | def load_values(self, values: dict):
38 | succeeded = False
39 | if self.left_operand_key is not None:
40 | try:
41 | self.left_operand_value = values[self.left_operand_key]
42 | succeeded = True
43 | except KeyError:
44 | pass
45 | if self.right_operand_key is not None:
46 | try:
47 | self.right_operand_value = values[self.right_operand_key]
48 | except KeyError:
49 | if not succeeded:
50 | # require at least one value read
51 | raise
52 |
53 | def is_filtered(self):
54 | if not self.is_valid():
55 | return False
56 | try:
57 | left_operand = decimal.Decimal(self.left_operand_value)
58 | except decimal.InvalidOperation:
59 | left_operand = str(self.left_operand_value)
60 | try:
61 | right_operand = decimal.Decimal(self.right_operand_value)
62 | except decimal.InvalidOperation:
63 | right_operand = str(self.right_operand_value)
64 | return logical_operators.evaluate_condition(left_operand, right_operand, self.operator)
65 |
66 | @classmethod
67 | def from_dict(cls, param_dict):
68 | return cls(
69 | param_dict[cls.LEFT_OPERAND_KEY_KEY],
70 | param_dict[cls.RIGHT_OPERAND_KEY_KEY],
71 | param_dict[cls.LEFT_OPERAND_VALUE_KEY],
72 | param_dict[cls.RIGHT_OPERAND_VALUE_KEY],
73 | param_dict[cls.OPERATOR_KEY],
74 | )
75 |
--------------------------------------------------------------------------------
/src/producers/evaluator_producer.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import SniperCallsbot_commons.enums as common_enums
17 |
18 | import SniperCallsbot_backtesting.api as backtesting_api
19 |
20 | import SniperCallsbot_evaluators.api as evaluator_api
21 | import SniperCallsbot_evaluators.SniperCallsbot_channel_consumer as evaluator_channel_consumer
22 |
23 | import src.channels as SniperCallsbot_channel
24 | import src.logger as logger
25 |
26 |
27 | class EvaluatorProducer(SniperCallsbot_channel.SniperCallsBotChannelProducer):
28 | """EvaluatorFactory class:
29 | - Create evaluators
30 | """
31 |
32 | def __init__(self, channel, SniperCallsbot):
33 | super().__init__(channel)
34 | self.SniperCallsbot = SniperCallsbot
35 | self.tentacles_setup_config = self.SniperCallsbot.tentacles_setup_config
36 |
37 | self.matrix_id = None
38 |
39 | async def start(self):
40 | await evaluator_api.initialize_evaluators(self.SniperCallsbot.config, self.tentacles_setup_config)
41 | self.matrix_id = evaluator_api.create_matrix()
42 | await evaluator_api.create_evaluator_channels(
43 | self.matrix_id, is_backtesting=backtesting_api.is_backtesting_enabled(self.SniperCallsbot.config)
44 | )
45 | await logger.init_evaluator_chan_logger(self.matrix_id)
46 |
47 | async def create_evaluators(self, exchange_configuration):
48 | await self.send(bot_id=self.SniperCallsbot.bot_id,
49 | subject=common_enums.SniperCallsBotChannelSubjects.CREATION.value,
50 | action=evaluator_channel_consumer.SniperCallsBotChannelEvaluatorActions.EVALUATOR.value,
51 | data={
52 | evaluator_channel_consumer.SniperCallsBotChannelEvaluatorDataKeys.TENTACLES_SETUP_CONFIG.value:
53 | self.SniperCallsbot.tentacles_setup_config,
54 | evaluator_channel_consumer.SniperCallsBotChannelEvaluatorDataKeys.MATRIX_ID.value:
55 | self.SniperCallsbot.evaluator_producer.matrix_id,
56 | evaluator_channel_consumer.SniperCallsBotChannelEvaluatorDataKeys.EXCHANGE_CONFIGURATION.value:
57 | exchange_configuration
58 | })
59 |
60 | async def stop(self):
61 | self.logger.debug("Stopping ...")
62 | await evaluator_api.stop_all_evaluator_channels(self.matrix_id)
63 | self.logger.debug("Stopped")
64 |
--------------------------------------------------------------------------------
/src/community/supabase_backend/configuration_storage.py:
--------------------------------------------------------------------------------
1 |
2 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
3 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
4 | #
5 | # SniperCallsBot is free software; you can redistribute it and/or
6 | # modify it under the terms of the GNU General Public License
7 | # as published by the Free Software Foundation; either
8 | # version 3.0 of the License, or (at your option) any later version.
9 | #
10 | # SniperCallsBot is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | # General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public
16 | # License along with SniperCallsBot. If not, see .
17 | import typing
18 | import gotrue
19 | import SniperCallsbot_commons.configuration
20 | import SniperCallsbot_commons.logging
21 | import src.constants
22 |
23 |
24 | class SyncConfigurationStorage(gotrue.SyncSupportedStorage):
25 | """
26 | Used by gotrue client to save authenticated user session
27 | """
28 | def __init__(self, configuration: SniperCallsbot_commons.configuration.Configuration):
29 | self.configuration: SniperCallsbot_commons.configuration.Configuration = configuration
30 |
31 | def get_item(self, key: str) -> typing.Optional[str]:
32 | return self._get_value_in_config(key)
33 |
34 | def set_item(self, key: str, value: str) -> None:
35 | self._save_value_in_config(key, value)
36 |
37 | def remove_item(self, key: str) -> None:
38 | self._save_value_in_config(key, "")
39 |
40 | def has_remote_packages(self) -> bool:
41 | return bool(
42 | self.configuration.config.get(src.constants.CONFIG_COMMUNITY, {}).get(
43 | src.constants.CONFIG_COMMUNITY_PACKAGE_URLS
44 | )
45 | )
46 |
47 | def _save_value_in_config(self, key, value):
48 | if self.configuration is not None:
49 | if src.constants.CONFIG_COMMUNITY not in self.configuration.config:
50 | self.configuration.config[src.constants.CONFIG_COMMUNITY] = {}
51 | self.configuration.config[src.constants.CONFIG_COMMUNITY][key] = value
52 | try:
53 | self.configuration.save()
54 | except Exception as err:
55 | SniperCallsbot_commons.logging.get_logger(self.__class__.__name__).exception(
56 | err, True, f"Error when saving configuration {err}"
57 | )
58 |
59 | def _get_value_in_config(self, key):
60 | if self.configuration is not None:
61 | try:
62 | return self.configuration.config[src.constants.CONFIG_COMMUNITY][key]
63 | except KeyError:
64 | return ""
65 | return None
66 |
67 |
68 | class ASyncConfigurationStorage(gotrue.AsyncSupportedStorage):
69 | def __init__(self, configuration: SniperCallsbot_commons.configuration.Configuration):
70 | self.sync_storage: SyncConfigurationStorage = SyncConfigurationStorage(configuration)
71 |
72 | async def get_item(self, key: str) -> typing.Optional[str]:
73 | return self.sync_storage.get_item(key)
74 |
75 | async def set_item(self, key: str, value: str) -> None:
76 | self.sync_storage.set_item(key, value)
77 |
78 | async def remove_item(self, key: str) -> None:
79 | self.sync_storage.remove_item(key)
80 |
--------------------------------------------------------------------------------
/static/img/btc.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/producers/exchange_producer.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import asyncio
17 |
18 | import SniperCallsbot_commons.enums as common_enums
19 | import SniperCallsbot_commons.constants as common_constants
20 |
21 | import SniperCallsbot_trading.api as trading_api
22 | import SniperCallsbot_trading.SniperCallsbot_channel_consumer as trading_channel_consumer
23 |
24 | import src.channels as SniperCallsbot_channel
25 |
26 |
27 | class ExchangeProducer(SniperCallsbot_channel.SniperCallsBotChannelProducer):
28 | def __init__(self, channel, SniperCallsbot, backtesting, ignore_config=False):
29 | super().__init__(channel)
30 | self.SniperCallsbot = SniperCallsbot
31 | self.ignore_config = ignore_config
32 |
33 | self.backtesting = backtesting
34 | self.exchange_manager_ids = []
35 |
36 | self.to_create_exchanges_count = 0
37 | self.created_all_exchanges = asyncio.Event()
38 |
39 | async def start(self):
40 | self.to_create_exchanges_count = 0
41 | self.created_all_exchanges.clear()
42 | for exchange_name in trading_api.get_enabled_exchanges_names(self.SniperCallsbot.config):
43 | await self.create_exchange(exchange_name, self.backtesting)
44 | self.to_create_exchanges_count += 1
45 |
46 | def register_created_exchange_id(self, exchange_id):
47 | self.exchange_manager_ids.append(exchange_id)
48 | if len(self.exchange_manager_ids) == self.to_create_exchanges_count:
49 | self.created_all_exchanges.set()
50 | self.logger.debug(f"Exchange(s) created")
51 |
52 | async def stop(self):
53 | self.logger.debug("Stopping ...")
54 | for exchange_manager in trading_api.get_exchange_managers_from_exchange_ids(self.exchange_manager_ids):
55 | await trading_api.stop_exchange(exchange_manager)
56 | self.logger.debug("Stopped")
57 |
58 | async def create_exchange(self, exchange_name, backtesting):
59 | await self.send(bot_id=self.SniperCallsbot.bot_id,
60 | subject=common_enums.SniperCallsBotChannelSubjects.CREATION.value,
61 | action=trading_channel_consumer.SniperCallsBotChannelTradingActions.EXCHANGE.value,
62 | data={
63 | trading_channel_consumer.SniperCallsBotChannelTradingDataKeys.TENTACLES_SETUP_CONFIG.value:
64 | self.SniperCallsbot.tentacles_setup_config,
65 | trading_channel_consumer.SniperCallsBotChannelTradingDataKeys.MATRIX_ID.value:
66 | self.SniperCallsbot.evaluator_producer.matrix_id,
67 | trading_channel_consumer.SniperCallsBotChannelTradingDataKeys.BACKTESTING.value: backtesting,
68 | trading_channel_consumer.SniperCallsBotChannelTradingDataKeys.EXCHANGE_CONFIG.value:
69 | self.SniperCallsbot.config,
70 | trading_channel_consumer.SniperCallsBotChannelTradingDataKeys.EXCHANGE_NAME.value: exchange_name,
71 | })
72 |
--------------------------------------------------------------------------------
/static/img/logo_big.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/sniperbot_backtesting_factory.py:
--------------------------------------------------------------------------------
1 | # This file is part of SniperCallsBot (https://github.com/Drakkar-Software/SniperCallsBot)
2 | # Copyright (c) 2023 Drakkar-Software, All rights reserved.
3 | #
4 | # SniperCallsBot is free software; you can redistribute it and/or
5 | # modify it under the terms of the GNU General Public License
6 | # as published by the Free Software Foundation; either
7 | # version 3.0 of the License, or (at your option) any later version.
8 | #
9 | # SniperCallsBot is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | # General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public
15 | # License along with SniperCallsBot. If not, see .
16 | import SniperCallsbot_backtesting.api as backtesting_api
17 | import SniperCallsbot_commons.configuration as configuration
18 | import SniperCallsbot_backtesting.constants as constants
19 |
20 | import src.api.backtesting as SniperCallsbot_backtesting_api
21 | import src.SniperCallsbot as SniperCallsbot_class
22 |
23 |
24 | class SniperCallsBotBacktestingFactory(SniperCallsbot_class.SniperCallsBot):
25 | def __init__(self, config: configuration.Configuration,
26 | log_report=True,
27 | run_on_common_part_only=True,
28 | enable_join_timeout=True,
29 | enable_logs=True):
30 | super().__init__(config, community_authenticator=_BacktestingCommunityAuthenticator())
31 | self.independent_backtesting = None
32 | self.log_report = log_report
33 | self.run_on_common_part_only = run_on_common_part_only
34 | self.enable_join_timeout = enable_join_timeout
35 | self.enable_logs = enable_logs
36 |
37 | async def initialize(self):
38 | try:
39 | await self.initializer.create(False)
40 | join_backtesting_timeout = constants.BACKTESTING_DEFAULT_JOIN_TIMEOUT if self.enable_join_timeout else None
41 | self.independent_backtesting = SniperCallsbot_backtesting_api.create_independent_backtesting(
42 | self.config,
43 | self.tentacles_setup_config,
44 | backtesting_api.get_backtesting_data_files(self.config),
45 | run_on_common_part_only=self.run_on_common_part_only,
46 | join_backtesting_timeout=join_backtesting_timeout,
47 | enable_logs=self.enable_logs,
48 | enforce_total_databases_max_size_after_run=True)
49 | await SniperCallsbot_backtesting_api.initialize_and_run_independent_backtesting(self.independent_backtesting,
50 | log_errors=False)
51 | await SniperCallsbot_backtesting_api.join_independent_backtesting(self.independent_backtesting,
52 | timeout=join_backtesting_timeout)
53 | if self.log_report:
54 | SniperCallsbot_backtesting_api.log_independent_backtesting_report(self.independent_backtesting)
55 | await SniperCallsbot_backtesting_api.stop_independent_backtesting(self.independent_backtesting, memory_check=False)
56 | except Exception as e:
57 | self.logger.exception(e, True, f"Error when starting backtesting: {e.__class__.__name__}")
58 | finally:
59 | self.task_manager.stop_tasks(stop_SniperCallsbot=False)
60 |
61 |
62 | class _BacktestingCommunityAuthenticator:
63 | """
64 | Used as a community mock in backtesting bots
65 | """
66 | def update(self, *args):
67 | pass
68 |
69 | def is_initialized(self):
70 | return True
71 |
72 | def is_using_the_current_loop(self):
73 | return True
74 |
75 | async def stop(self):
76 | pass
77 |
--------------------------------------------------------------------------------