├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── account └── templates │ └── account │ ├── login.html │ ├── profile.html │ └── register.html ├── djangoTrade ├── __init__.py ├── celery.py ├── routing.py ├── settings.py ├── urls.py └── wsgi.py ├── dump.json ├── images ├── candelsticks.jpg ├── final_screen.jpg ├── home_page.jpg └── ongrid-systems-cover.png ├── manage.py ├── requirements.txt ├── templates └── 404.html ├── ticker_app ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── routers.py ├── tests.py └── views.py ├── trade ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── static │ ├── css │ │ ├── highcharts.css │ │ ├── images │ │ │ ├── animated-overlay.gif │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ ├── ui-icons_454545_256x240.png │ │ │ ├── ui-icons_888888_256x240.png │ │ │ └── ui-icons_cd0a0a_256x240.png │ │ ├── jqChart.css │ │ ├── jqRangeSlider.css │ │ ├── jquery-ui-1.10.4.css │ │ ├── materialize.css │ │ ├── setup.css │ │ └── style.css │ ├── fonts │ │ └── roboto │ │ │ ├── Roboto-Bold.woff │ │ │ ├── Roboto-Bold.woff2 │ │ │ ├── Roboto-Light.woff │ │ │ ├── Roboto-Light.woff2 │ │ │ ├── Roboto-Medium.woff │ │ │ ├── Roboto-Medium.woff2 │ │ │ ├── Roboto-Regular.woff │ │ │ ├── Roboto-Regular.woff2 │ │ │ ├── Roboto-Thin.woff │ │ │ └── Roboto-Thin.woff2 │ ├── images │ │ ├── cryptotokens │ │ │ ├── .png │ │ │ ├── ardor.png │ │ │ ├── augur.png │ │ │ ├── bitcoin.png │ │ │ ├── bitcoindark.png │ │ │ ├── bitconnect.png │ │ │ ├── bitshares.png │ │ │ ├── blackcoin.png │ │ │ ├── blocknet.png │ │ │ ├── bytecoin-bcn.png │ │ │ ├── counterparty.png │ │ │ ├── dash.png │ │ │ ├── decred.png │ │ │ ├── digibyte.png │ │ │ ├── dogecoin.png │ │ │ ├── ethereum-classic.png │ │ │ ├── ethereum.png │ │ │ ├── etheroll.png │ │ │ ├── factom.png │ │ │ ├── gamecredits.png │ │ │ ├── gnosis-gno.png │ │ │ ├── golem-network-tokens.png │ │ │ ├── library-credit.png │ │ │ ├── lisk.png │ │ │ ├── litecoin.png │ │ │ ├── maidsafecoin.png │ │ │ ├── monero.png │ │ │ ├── namecoin.png │ │ │ ├── nem.png │ │ │ ├── nxt.png │ │ │ ├── peercoin.png │ │ │ ├── potcoin.png │ │ │ ├── reddcoin.png │ │ │ ├── ripple.png │ │ │ ├── siacoin.png │ │ │ ├── steem.png │ │ │ ├── stratis.png │ │ │ ├── syscoin.png │ │ │ ├── tether.png │ │ │ ├── viacoin.png │ │ │ └── zcash.png │ │ └── logo.png │ ├── js │ │ ├── coinmarketcup.js │ │ ├── exporting.js │ │ ├── highstock.js │ │ ├── jqChart.js │ │ ├── jqRangeSlider.js │ │ ├── materialize.js │ │ ├── script.js │ │ └── setup.js │ └── trade │ │ └── 404.jpg ├── tasks.py ├── templates │ ├── account │ │ ├── account_inactive.html │ │ ├── base.html │ │ ├── email.html │ │ ├── email │ │ │ ├── email_confirmation_message.txt │ │ │ ├── email_confirmation_signup_message.txt │ │ │ ├── email_confirmation_signup_subject.txt │ │ │ ├── email_confirmation_subject.txt │ │ │ ├── password_reset_key_message.txt │ │ │ └── password_reset_key_subject.txt │ │ ├── email_confirm.html │ │ ├── login.html │ │ ├── logout.html │ │ ├── messages │ │ │ ├── cannot_delete_primary_email.txt │ │ │ ├── email_confirmation_sent.txt │ │ │ ├── email_confirmed.txt │ │ │ ├── email_deleted.txt │ │ │ ├── logged_in.txt │ │ │ ├── logged_out.txt │ │ │ ├── password_changed.txt │ │ │ ├── password_set.txt │ │ │ ├── primary_email_set.txt │ │ │ └── unverified_primary_email.txt │ │ ├── password_change.html │ │ ├── password_reset.html │ │ ├── password_reset_done.html │ │ ├── password_reset_from_key.html │ │ ├── password_reset_from_key_done.html │ │ ├── password_set.html │ │ ├── signup.html │ │ ├── signup_closed.html │ │ ├── snippets │ │ │ └── already_logged_in.html │ │ ├── verification_sent.html │ │ └── verified_email_required.html │ ├── openid │ │ ├── base.html │ │ └── login.html │ ├── socialaccount │ │ ├── authentication_error.html │ │ ├── base.html │ │ ├── connections.html │ │ ├── login_cancelled.html │ │ ├── messages │ │ │ ├── account_connected.txt │ │ │ ├── account_connected_other.txt │ │ │ └── account_disconnected.txt │ │ ├── signup.html │ │ └── snippets │ │ │ ├── login_extra.html │ │ │ └── provider_list.html │ └── trade │ │ ├── base.html │ │ ├── coins.html │ │ ├── home.html │ │ ├── transactions.html │ │ ├── user_summaries.html │ │ └── wallet_info.html ├── templatetags │ ├── __init__.py │ ├── coin_full_name.py │ ├── coins.py │ ├── summary_balance.py │ ├── transactions.py │ ├── value_to_cryptotoken.py │ └── wallet_information.py ├── tests.py └── views.py ├── tradeBOT ├── __init__.py ├── admin.py ├── apps.py ├── consumers.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── tasks.py ├── templates │ └── tradeBOT │ │ ├── Coins.html │ │ ├── coin_info.html │ │ ├── exchange_primary_coins.html │ │ ├── get_primary_pairs.html │ │ ├── index.html │ │ ├── orders.html │ │ ├── pairs.html │ │ ├── primary_coin_pairs.html │ │ ├── relations.html │ │ ├── setup.html │ │ ├── test.html │ │ ├── to_trade.html │ │ └── user_primary.html ├── templatetags │ ├── __init__.py │ ├── get_coin_info.py │ ├── get_exchange_coins.py │ ├── relations.py │ └── tradeBot_filters.py ├── tests.py └── views.py └── user_profile ├── __init__.py ├── admin.py ├── apps.py ├── migrations └── __init__.py ├── models.py ├── templates └── user_profile │ └── profile.html ├── tests.py └── views.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Linux template 3 | *~ 4 | 5 | # temporary files which can be created if a process still has a handle open of a deleted file 6 | .fuse_hidden* 7 | 8 | # KDE directory preferences 9 | .directory 10 | 11 | # Linux trash folder which might appear on any partition or disk 12 | .Trash-* 13 | 14 | # .nfs files are created when an open file is removed but is still being accessed 15 | .nfs* 16 | ### Python template 17 | # Byte-compiled / optimized / DLL files 18 | __pycache__/ 19 | *.py[cod] 20 | *$py.class 21 | 22 | # C extensions 23 | *.so 24 | 25 | # Distribution / packaging 26 | .Python 27 | build/ 28 | develop-eggs/ 29 | dist/ 30 | downloads/ 31 | eggs/ 32 | .eggs/ 33 | lib/ 34 | lib64/ 35 | parts/ 36 | sdist/ 37 | var/ 38 | wheels/ 39 | *.egg-info/ 40 | .installed.cfg 41 | *.egg 42 | MANIFEST 43 | 44 | # PyInstaller 45 | # Usually these files are written by a python script from a template 46 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 47 | *.manifest 48 | *.spec 49 | 50 | # Installer logs 51 | pip-log.txt 52 | pip-delete-this-directory.txt 53 | 54 | # Unit test / coverage reports 55 | htmlcov/ 56 | .tox/ 57 | .coverage 58 | .coverage.* 59 | .cache 60 | nosetests.xml 61 | coverage.xml 62 | *.cover 63 | .hypothesis/ 64 | 65 | # Translations 66 | *.mo 67 | *.pot 68 | 69 | # Django stuff: 70 | *.log 71 | .static_storage/ 72 | .media/ 73 | local_settings.py 74 | 75 | # Flask stuff: 76 | instance/ 77 | .webassets-cache 78 | 79 | # Scrapy stuff: 80 | .scrapy 81 | 82 | # Sphinx documentation 83 | docs/_build/ 84 | 85 | # PyBuilder 86 | target/ 87 | 88 | # Jupyter Notebook 89 | .ipynb_checkpoints 90 | 91 | # pyenv 92 | .python-version 93 | 94 | # celery beat schedule file 95 | celerybeat-schedule 96 | 97 | # SageMath parsed files 98 | *.sage.py 99 | 100 | # Environments 101 | .env 102 | .venv 103 | env/ 104 | venv/ 105 | ENV/ 106 | env.bak/ 107 | venv.bak/ 108 | 109 | # Spyder project settings 110 | .spyderproject 111 | .spyproject 112 | 113 | # Rope project settings 114 | .ropeproject 115 | 116 | # mkdocs documentation 117 | /site 118 | 119 | # mypy 120 | .mypy_cache/ 121 | ### JetBrains template 122 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 123 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 124 | 125 | # User-specific stuff: 126 | .idea/**/workspace.xml 127 | .idea/**/tasks.xml 128 | .idea/dictionaries 129 | 130 | # Sensitive or high-churn files: 131 | .idea/**/dataSources/ 132 | .idea/**/dataSources.ids 133 | .idea/**/dataSources.xml 134 | .idea/**/dataSources.local.xml 135 | .idea/**/sqlDataSources.xml 136 | .idea/**/dynamic.xml 137 | .idea/**/uiDesigner.xml 138 | 139 | # Gradle: 140 | .idea/**/gradle.xml 141 | .idea/**/libraries 142 | 143 | # CMake 144 | cmake-build-debug/ 145 | 146 | # Mongo Explorer plugin: 147 | .idea/**/mongoSettings.xml 148 | 149 | ## File-based project format: 150 | *.iws 151 | 152 | ## Plugin-specific files: 153 | 154 | # IntelliJ 155 | out/ 156 | 157 | # mpeltonen/sbt-idea plugin 158 | .idea_modules/ 159 | 160 | # JIRA plugin 161 | atlassian-ide-plugin.xml 162 | 163 | # Cursive Clojure plugin 164 | .idea/replstate.xml 165 | 166 | # Crashlytics plugin (for Android Studio and IntelliJ) 167 | com_crashlytics_export_strings.xml 168 | crashlytics.properties 169 | crashlytics-build.properties 170 | fabric.properties 171 | 172 | .idea/ 173 | /logs/ 174 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 OnGrid Systems 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![OnGrid Systems Blockchain Applications DApps Development](images/ongrid-systems-cover.png)](https://ongrid.pro/) 2 | 3 | ![GitHub last commit](https://img.shields.io/github/last-commit/OnGridSystems/CATEd.svg) 4 | ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/Django.svg) 5 | ![License](https://img.shields.io/github/license/mashape/apistatus.svg) 6 | 7 | 8 | # CATEd - Cryptocurrency Analytics and Trading Engine for Django 9 | 10 | ## Overview 11 | 12 | [HabraHabr article in Russian](https://habrahabr.ru/users/proofx/posts/) 13 | 14 | CATEd is the cryptocurrency trading bot written on Python 3 with feature-rich management Web interface (Django, Celery). 15 | 16 | Main features: 17 | * View the status of exchange accounts, transactions and orders on them; 18 | * View the status of cold wallets and transactions details; 19 | * History of deposits and withdrawals on graphical diagram; 20 | * Configurable buy/sell/hold logic, (allowed tokens and proportions); 21 | * Keeping the balances of different tokens at the configured levels; 22 | 23 | ![home_page](https://github.com/OnGridSystems/CATEd/blob/master/images/home_page.jpg) 24 | 25 | ![main_bot_page](https://github.com/OnGridSystems/CATEd/blob/master/images/final_screen.jpg) 26 | 27 | ## Install 28 | 29 | You need python3, mysql-server, rabbitmq-server and redis-server to be installed. 30 | 31 | Create python virtual env and activate it in your favorite way. 32 | 33 | Clone project 34 | ```sh 35 | git clone git@github.com:OnGridSystems/CATEd.git 36 | ``` 37 | Go to project dir 38 | ```sh 39 | cd CATEd 40 | ``` 41 | Create mysql databases 42 | ```sh 43 | echo "create database trade character set utf8; create database celery_result; create database portal_ticker;" | mysql -u root 44 | ``` 45 | And migrate 46 | ```sh 47 | python manage.py migrate 48 | ``` 49 | Load initial data with some exchanges and wallets 50 | ```sh 51 | python manage.py loaddata dump.json 52 | ``` 53 | 54 | Create you own superuser with 55 | ```sh 56 | python manage.py createsuperuser 57 | ``` 58 | Before starting the bot should read the list of currencies from the site coinmarketcup.com. To do this run following code 59 | with activated virtual environment. 60 | ```sh 61 | read -d "" PYTASKS <<"EOF" 62 | from tradeBOT import tasks 63 | coinmarketcup = tasks.pull_coinmarketcup() 64 | EOF 65 | echo "$PYTASKS" | python manage.py shell 66 | ``` 67 | And runserver 68 | ```sh 69 | python manage.py runserver 70 | ``` 71 | Now you can add your api keys. 72 | 73 | **Add NEW api keys for use bot.** 74 | 75 | To do this open http://127.0.0.1:8000/ in your browser, login and click red "plus" button in the lower right corner. 76 | 77 | Bot uses several celery queues for trade, and main is triggered by a signal from a first worker named celery@worker_high. 78 | Another worker - worker_set_orders checks for already existing orders and try keeps them up to date. 79 | There are also queues low and normal, for calculating users' orders and pulling their balances. 80 | 81 | You can run celery in several terminal windows or screen sessions: 82 | ```sh 83 | celery worker -A djangoTrade -n worker_high -l info -c 1 -Q high 84 | celery worker -A djangoTrade -n worker_set_orders -l info -c 1 -Q set_orders 85 | celery worker -A djangoTrade -n worker_low -l info -c 2 -Q low 86 | celery worker -A djangoTrade -n worker_normal -l info -c 2 -Q normal 87 | ``` 88 | 89 | Example of running celery with supervisor daemon: 90 | 91 | ```sh 92 | wget https://raw.githubusercontent.com/celery/celery/4.0/extra/generic-init.d/celeryd -O /etc/init.d/celeryd 93 | wget https://raw.githubusercontent.com/celery/celery/4.0/extra/generic-init.d/celerybeat -O /etc/init.d/celerybeat 94 | chmod +x /etc/init.d/celeryd /etc/init.d/celerybeat 95 | 96 | #add celery config 97 | read -d "" CELERYD_CFG <<"EOF" 98 | CELERYD_NODES="worker_set_orders worker_low worker_normal worker_high" 99 | CELERY_BIN="/opt/env/bin/python -m celery" 100 | CELERY_APP="djangoTrade" 101 | CELERYD_CHDIR="/opt/ongrid_portal" 102 | CELERYD_OPTS="-Q:worker_set_orders set_orders -Q:worker_low low -Q:worker_normal normal -Q:worker_high high -c:worker_set_orders 1 -c:worker_low 3 -c:worker_normal 3 -c:worker_high 1" 103 | CELERYD_LOG_FILE="/var/log/celery/%n%I.log" 104 | CELERYD_PID_FILE="/var/run/celery/%n.pid" 105 | CELERYD_USER="root" 106 | CELERYD_GROUP="root" 107 | DJANGO_SETTINGS_MODULE="djangoTrade.settings" 108 | CELERY_CREATE_DIRS=1 109 | SECRET_KEY="ada#qadaa2d#1232%!^&#*(&@(!&Y!&#*T!@(^F#!@&#F!@&#F!(@" 110 | EOF 111 | echo "$CELERYD_CFG" > /etc/default/celeryd 112 | 113 | read -d "" CELERYBEAT_CFG <<"EOF" 114 | CELERY_BIN="/opt/env/bin/python -m celery" 115 | CELERY_APP="djangoTrade" 116 | CELERYD_CHDIR="/opt/ongrid_portal" 117 | DJANGO_SETTINGS_MODULE="djangoTrade.settings" 118 | CELERYBEAT_USER="root" 119 | CELERYBEAT_GROUP="root" 120 | EOF 121 | echo "$CELERYBEAT_CFG" > /etc/default/celerybeat 122 | 123 | /etc/init.d/celeryd create-paths 124 | /etc/init.d/celeryd start 125 | /etc/init.d/celeryd stop 126 | /etc/init.d/celerybeat create-paths 127 | /etc/init.d/celerybeat start 128 | /etc/init.d/celerybeat stop 129 | sudo update-rc.d celeryd defaults 130 | sudo update-rc.d celerybeat defaults 131 | ``` 132 | 133 | ## Authors 134 | * OnGrid Systems: [Site](https://ongrid.pro), [GitHub](https://github.com/OnGridSystems/), [FaceBook](https://www.facebook.com/ongrid.pro/), [Youtube](https://www.youtube.com/channel/UCT8s-f1FInO6ivn_dp-W34g), [LinkedIn](https://www.linkedin.com/company/ongridpro/) 135 | * Sergey Korotko [FaceBook](https://www.facebook.com/s.korotko), [GitHub](https://github.com/achievement008) 136 | * Dmitry Suldin [FaceBook](https://www.facebook.com/novator.klin), [GitHub](https://github.com/Klyaus) 137 | * Kirill Varlamov: [GitHub](https://github.com/ongrid/), [FaceBook](https://www.facebook.com/kirill.varlamov.12), [LinkedIn](https://www.linkedin.com/in/kvarlamo/) 138 | 139 | ## License 140 | 141 | Copyright (c) 2018 OnGrid Systems. 142 | 143 | Each file included in this repository is licensed under the [MIT license](LICENSE). -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/__init__.py -------------------------------------------------------------------------------- /account/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'trade/base.html' %} 2 | {% block content %} 3 |
4 |

Авторизация

5 |
6 | {% csrf_token %} 7 | {% if errors %} 8 | {{ errors }} 9 | {% endif %} 10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 | 19 |
20 |
21 | {% endblock %} -------------------------------------------------------------------------------- /account/templates/account/profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'trade/base.html' %} 2 | {% block content %} 3 |

Мой профиль

4 |
5 |
6 |
7 |
Complete your user profile to increase your limits.
8 |
9 |
10 | {% csrf_token %} 11 |
12 | 15 | 18 |
19 |
20 | 23 | 25 |
26 |
27 | 30 | 32 |
33 | 36 |
37 | {{ form.as_p }} 38 |
39 |
40 |
41 |
42 | {% endblock %} -------------------------------------------------------------------------------- /account/templates/account/register.html: -------------------------------------------------------------------------------- 1 | {% extends 'trade/base.html' %} 2 | {% block content %} 3 |
4 |

Регистрация

5 |
6 | {% csrf_token %} 7 | {% if form.errors %} 8 | {% for error in form.username.errors %} 9 | {{ error }} 10 | {% endfor %} 11 |
12 | {% for error in form.password2.errors %} 13 | {{ error }} 14 | {% endfor %} 15 | {% endif %} 16 | {% for f in form %} 17 |
18 | 19 | {{ f }} 20 |
21 | {{ f.help_text | safe }} 22 | {% endfor %} 23 | 24 |
25 |
26 | {% endblock %} -------------------------------------------------------------------------------- /djangoTrade/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from .celery import app as celery_app -------------------------------------------------------------------------------- /djangoTrade/celery.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | import os 3 | from celery import Celery 4 | from django.conf import settings 5 | from kombu import Queue, Exchange 6 | 7 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoTrade.settings') 8 | app = Celery('djangoTrade') 9 | app.config_from_object('django.conf:settings') 10 | app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) 11 | app.conf.task_queues = { 12 | Queue('high', Exchange('high'), routing_key='high'), 13 | Queue('normal', Exchange('normal'), routing_key='normal'), 14 | Queue('low', Exchange('low'), routing_key='low'), 15 | Queue('set_orders', Exchange('set_orders'), routing_key='set_orders'), 16 | } 17 | app.conf.task_default_queue = 'normal' 18 | app.conf.task_default_exchange_type = 'direct' 19 | app.conf.task_default_routing_key = 'normal' 20 | 21 | 22 | @app.task(bind=True) 23 | def debug_task(self): 24 | print('Request: {0!r}'.format(self.request)) 25 | -------------------------------------------------------------------------------- /djangoTrade/routing.py: -------------------------------------------------------------------------------- 1 | from channels.routing import route 2 | from tradeBOT.consumers import ws_add, ws_disconnect 3 | 4 | channel_routing = [ 5 | route("websocket.connect", ws_add, path=r'^/trade/'), 6 | route("websocket.disconnect", ws_disconnect), 7 | ] 8 | -------------------------------------------------------------------------------- /djangoTrade/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for djangoTrade project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.11.1. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.11/ref/settings/ 11 | """ 12 | from __future__ import absolute_import, unicode_literals 13 | import os 14 | 15 | # Celery options 16 | from kombu import Queue, Exchange 17 | 18 | CELERY_BROKER_URL = 'amqp://guest:guest@localhost//' 19 | CELERY_ACCEPT_CONTENT = ['json'] 20 | CELERY_RESULT_BACKEND = 'db+mysql://root:@localhost/celery_result' 21 | CELERY_TASK_SERIALIZER = 'json' 22 | CELERY_TIMEZONE = 'Europe/Moscow' 23 | CELERY_SEND_TASK_ERROR_EMAILS = False 24 | CELERYD_MAX_TASKS_PER_CHILD = 5 25 | 26 | CELERY_ROUTES = { 27 | 'trade.tasks.pull_exchanges_balances': {'queue': 'low'}, 28 | 'trade.tasks.pull_exchanges_tickers': {'queue': 'low'}, 29 | } 30 | 31 | CELERY_CREATE_MISSING_QUEUES = True 32 | 33 | # AllAuth setting 34 | ACCOUNT_EMAIL_REQUIRED = True 35 | ACCOUNT_AUTHENTICATION_METHOD = 'username_email' 36 | ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1 37 | LOGIN_REDIRECT_URL = '/' 38 | ACCOUNT_LOGOUT_REDIRECT_URL = '/' 39 | ACCOUNT_LOGOUT_ON_PASSWORD_CHANGE = True 40 | 41 | # redis sessions 42 | SESSION_ENGINE = 'redis_sessions.session' 43 | 44 | # Email 45 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 46 | 47 | DEFAULT_INDEX_TABLESPACE = 10 48 | 49 | ADMINS = (('Сергей', 'achievement008@gmail.com'),) 50 | 51 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 52 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 53 | 54 | # Quick-start development settings - unsuitable for production 55 | # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ 56 | 57 | # SECURITY WARNING: keep the secret key used in production secret! 58 | SECRET_KEY = '1j&=q!62_%51y9!=97n=)bel8+#y+lup1bsy31d%s=sm!9q_c+' 59 | 60 | # SECURITY WARNING: don't run with debug turned on in production! 61 | DEBUG = True 62 | 63 | ALLOWED_HOSTS = ['*'] 64 | 65 | # Application definition 66 | 67 | INSTALLED_APPS = [ 68 | 'django.contrib.admin', 69 | 'django.contrib.auth', 70 | 'django.contrib.contenttypes', 71 | 'django.contrib.sessions', 72 | 'django.contrib.messages', 73 | 'django.contrib.staticfiles', 74 | 'django.contrib.sites', 75 | 'trade', 76 | 'tradeBOT', 77 | 'user_profile', 78 | 'django_celery_beat', 79 | 'allauth', 80 | 'allauth.account', 81 | 'allauth.socialaccount', 82 | 'django.contrib.humanize', 83 | 'ticker_app', 84 | 'django_extensions', 85 | 'channels', 86 | ] 87 | 88 | SITE_ID = 1 89 | 90 | MIDDLEWARE = [ 91 | 'django.middleware.security.SecurityMiddleware', 92 | 'django.contrib.sessions.middleware.SessionMiddleware', 93 | 'django.middleware.common.CommonMiddleware', 94 | 'django.middleware.csrf.CsrfViewMiddleware', 95 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 96 | 'django.contrib.messages.middleware.MessageMiddleware', 97 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 98 | ] 99 | 100 | AUTHENTICATION_BACKENDS = ( 101 | 'django.contrib.auth.backends.ModelBackend', 102 | 'allauth.account.auth_backends.AuthenticationBackend', 103 | ) 104 | 105 | ROOT_URLCONF = 'djangoTrade.urls' 106 | 107 | TEMPLATES = [ 108 | { 109 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 110 | 'DIRS': [], 111 | 'APP_DIRS': True, 112 | 'OPTIONS': { 113 | 'context_processors': [ 114 | 'django.template.context_processors.debug', 115 | 'django.template.context_processors.request', 116 | 'django.contrib.auth.context_processors.auth', 117 | 'django.contrib.messages.context_processors.messages', 118 | ], 119 | }, 120 | }, 121 | ] 122 | 123 | WSGI_APPLICATION = 'djangoTrade.wsgi.application' 124 | 125 | # Database 126 | # https://docs.djangoproject.com/en/1.11/ref/settings/#databases 127 | 128 | DATABASES = { 129 | 'default': { 130 | 'ENGINE': 'django.db.backends.mysql', 131 | 'NAME': 'trade', 132 | 'USER': 'root', 133 | 'PASSWORD': '', 134 | 'default-character-set': 'utf-8', 135 | }, 136 | 'portal_ticker': { 137 | 'ENGINE': 'django.db.backends.mysql', 138 | 'NAME': 'portal_ticker', 139 | 'USER': 'root', 140 | 'PASSWORD': '', 141 | } 142 | } 143 | 144 | DATABASE_ROUTERS = ['ticker_app.routers.DBRouter', 'ticker_app.routers.PrimaryRouter'] 145 | 146 | # Password validation 147 | # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators 148 | 149 | AUTH_PASSWORD_VALIDATORS = [ 150 | { 151 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 152 | }, 153 | { 154 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 155 | }, 156 | { 157 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 158 | }, 159 | { 160 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 161 | }, 162 | ] 163 | 164 | # Internationalization 165 | # https://docs.djangoproject.com/en/1.11/topics/i18n/ 166 | 167 | LANGUAGE_CODE = 'en-US' 168 | 169 | TIME_ZONE = 'Europe/Moscow' 170 | 171 | USE_I18N = True 172 | 173 | USE_L10N = True 174 | 175 | USE_TZ = True 176 | 177 | STATIC_URL = '/static/' 178 | 179 | LOGIN_URL = '/accounts/login/' 180 | 181 | # yandex money settings 182 | YANDEX_MONEY_CLIENT_ID = None # set before start 183 | 184 | YANDEX_MONEY_REDIRECT_URI = None # set before start 185 | 186 | YANDEX_MONEY_CLIENT_SECRET = None # set before start 187 | 188 | STATIC_ROOT = '/opt/portal_ongrid/static' 189 | MEDIA_ROOT = '/opt/portal_ongrid/media' 190 | MEDIA_URL = '/media/' 191 | 192 | # channels 193 | CHANNEL_LAYERS = { 194 | "default": { 195 | "BACKEND": "asgi_redis.RedisChannelLayer", 196 | "CONFIG": { 197 | "hosts": [("localhost", 6379)], 198 | }, 199 | "ROUTING": "djangoTrade.routing.channel_routing", 200 | }, 201 | } 202 | 203 | # минимальное значение изменения цены за секунду 204 | DEPTH_COEFFICIENT = 0.5 205 | 206 | # активные биржи для торговли 207 | TRADING_EXCHANGES = ['poloniex'] 208 | 209 | # Time to life order, mins 210 | ORDER_TTL = 5 211 | 212 | # минимальное кол-во элементов серии 213 | RATE_CHANGE_SERIES_MIN_COUNT = 2 214 | 215 | # количество направлений 216 | DIRECTIONS_COUNT = 7 217 | 218 | # количество однонапрвленных (первых) направлений 219 | UNIDIRECTIONAL_COUNT = 4 220 | -------------------------------------------------------------------------------- /djangoTrade/urls.py: -------------------------------------------------------------------------------- 1 | """djangoTrade URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.11/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.conf.urls import url, include 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 | """ 16 | from django.conf import settings 17 | from django.conf.urls import url, include 18 | from django.conf.urls.static import static 19 | from django.contrib import admin 20 | from trade import views as tradeViews 21 | from tradeBOT import views as tradeBOTViews 22 | from ticker_app import views as tickerViews 23 | from allauth import urls as allauth_urls 24 | from user_profile import views as user_profile_views 25 | from django.contrib.auth.decorators import permission_required 26 | 27 | urlpatterns = [ 28 | url(r'^admin/', admin.site.urls), 29 | url(r'^accounts/', include(allauth_urls)), 30 | url(r'^profile/$', user_profile_views.profile, name='user_profile'), 31 | url(r'^change_status/$', permission_required('is_superuser')(tradeViews.change_status), 32 | name='change_status'), 33 | url(r'^$', tradeViews.index, name='index'), 34 | url(r'^exchange/$', permission_required('is_superuser')(tradeViews.exchange), name='exchange'), 35 | url(r'^wallet/$', permission_required('is_superuser')(tradeViews.wallet), name='wallet'), 36 | url(r'^api/$', tradeViews.get_holding, name='get_holding'), 37 | url(r'^transaction/new_comment/$', 38 | permission_required('is_superuser')(tradeViews.add_new_transaction_comment), name='new_comment'), 39 | url(r'^trade/setup/(?P[0-9]+)/$', tradeBOTViews.setup, name='tradeBotSetup'), 40 | url(r'^trade/addusercoin/$', tradeBOTViews.add_user_pair, name='add_user_pair'), 41 | url(r'^trade/changerank/$', tradeBOTViews.change_rank, name='changerank'), 42 | url(r'^trade/set_share/$', tradeBOTViews.set_share, name='set_share'), 43 | url(r'^trade/set_pair_add/$', tradeBOTViews.set_pair_add, name='set_pair_add'), 44 | url(r'^trade/delete_user_pair/$', tradeBOTViews.delete_user_pair, name='delete_user_pair'), 45 | url(r'^trade/change_primary_coin/$', tradeBOTViews.change_primary_coin, name='change_primary_coin'), 46 | url(r'^trade/change_primary_coin_rank/$', tradeBOTViews.change_primary_coin_rank, 47 | name='change_primary_coin_rank'), 48 | url(r'^trade/relations/$', tradeBOTViews.relations, name='relations'), 49 | url(r'^trade/exchange_script_activity/$', tradeBOTViews.change_user_exchange_script_activity, 50 | name='change_user_exchange_script_activity'), 51 | url(r'^trade/exchange_depth_to_trade/$', tradeBOTViews.exchange_depth_to_trade, 52 | name='exchange_depth_to_trade'), 53 | url(r'^trade/get_ticker/$', tickerViews.get_ticker, name='get_ticker'), 54 | url(r'^trade/get_new_orders_to_trade/$', tradeBOTViews.get_new_to_trade, name='get_new_to_trade'), 55 | ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 56 | -------------------------------------------------------------------------------- /djangoTrade/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for djangoTrade project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoTrade.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /dump.json: -------------------------------------------------------------------------------- 1 | [{"model": "trade.exchanges", "pk": 1, "fields": {"name": "poloniex", "info_frozen_key": "-isFrozen"}}, {"model": "trade.wallets", "pk": 1, "fields": {"name": "BTC"}}, {"model": "trade.wallets", "pk": 2, "fields": {"name": "ETH"}}, {"model": "trade.wallets", "pk": 3, "fields": {"name": "Yandex Money"}}] -------------------------------------------------------------------------------- /images/candelsticks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/images/candelsticks.jpg -------------------------------------------------------------------------------- /images/final_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/images/final_screen.jpg -------------------------------------------------------------------------------- /images/home_page.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/images/home_page.jpg -------------------------------------------------------------------------------- /images/ongrid-systems-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/images/ongrid-systems-cover.png -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | if __name__ == "__main__": 5 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoTrade.settings") 6 | try: 7 | from django.core.management import execute_from_command_line 8 | except ImportError: 9 | # The above import may fail for some other reason. Ensure that the 10 | # issue is really that Django is missing to avoid masking other 11 | # exceptions on Python 2. 12 | try: 13 | import django 14 | except ImportError: 15 | raise ImportError( 16 | "Couldn't import Django. Are you sure it's installed and " 17 | "available on your PYTHONPATH environment variable? Did you " 18 | "forget to activate a virtual environment?" 19 | ) 20 | raise 21 | execute_from_command_line(sys.argv) 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiodns==1.1.1 2 | aiohttp==2.2.5 3 | amqp==2.2.2 4 | anyjson==0.3.3 5 | asgi-redis==1.4.2 6 | asgiref==1.1.2 7 | asn1crypto==0.22.0 8 | async-timeout==1.4.0 9 | attrs==17.2.0 10 | autobahn==17.7.1 11 | Automat==0.6.0 12 | Babel==2.4.0 13 | bcrypt==3.1.3 14 | billiard==3.5.0.3 15 | bittrex==0.1.4 16 | cchardet==2.1.1 17 | ccxt==1.8.49 18 | celery==4.1.0 19 | certifi==2017.4.17 20 | cffi==1.10.0 21 | channels==1.1.6 22 | chardet==3.0.4 23 | constantly==15.1.0 24 | coverage==4.4.1 25 | cryptography==1.9 26 | daemon==1.1 27 | daphne==1.3.0 28 | defusedxml==0.5.0 29 | Django==1.11.5 30 | django-allauth==0.32.0 31 | django-celery==3.2.1 32 | django-celery-beat==1.0.1 33 | django-extensions==2.0.6 34 | django-redis-sessions==0.5.6 35 | flower==0.9.1 36 | future==0.16.0 37 | gevent==1.2.2 38 | greenlet==0.4.12 39 | gunicorn==19.7.1 40 | hyperlink==17.3.0 41 | idna==2.5 42 | incremental==17.5.0 43 | jsonpickle==0.9.5 44 | kombu==4.1.0 45 | msgpack-python==0.4.8 46 | multidict==3.2.0 47 | mysqlclient==1.3.10 48 | oauthlib==2.0.2 49 | paramiko==2.2.1 50 | poloniex==0.0.7 51 | pyasn1==0.2.3 52 | pyasn1-modules==0.0.9 53 | pycares==2.3.0 54 | pycparser==2.17 55 | PyNaCl==1.1.2 56 | pyOpenSSL==17.0.0 57 | pyTelegramBotAPI==3.2.0 58 | python3-openid==3.1.0 59 | pytz==2018.4 60 | redis==2.10.5 61 | requests==2.18.4 62 | requests-oauthlib==0.8.0 63 | service-identity==17.0.0 64 | signalr-client==0.0.7 65 | six==1.10.0 66 | slackclient==1.0.9 67 | SQLAlchemy==1.2.6 68 | sseclient==0.0.18 69 | TelegramBotAPI==0.3.2 70 | tornado==4.2 71 | Twisted==17.5.0 72 | txaio==2.8.1 73 | urllib3==1.21.1 74 | vine==1.1.4 75 | websocket==0.2.1 76 | websocket-client==0.44.0 77 | websockets==3.3 78 | yandex-money-sdk==0.1.3 79 | yarl==0.12.0 80 | zope.interface==4.4.2 81 | pip==10.0.0 82 | -------------------------------------------------------------------------------- /templates/404.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | You've ripped a hole in the fabric of the internet. Love, Chris from CSS-Tricks 7 | 8 | 9 | Page Not Found (404). 11 | 12 | -------------------------------------------------------------------------------- /ticker_app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/ticker_app/__init__.py -------------------------------------------------------------------------------- /ticker_app/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from ticker_app import models 3 | 4 | 5 | class ExchangeTickerAdmin(admin.ModelAdmin): 6 | list_display = [field.name for field in models.ExchangeTicker._meta.fields] 7 | 8 | class Meta: 9 | model = models.ExchangeTicker 10 | 11 | admin.site.register(models.ExchangeTicker, ExchangeTickerAdmin) 12 | -------------------------------------------------------------------------------- /ticker_app/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class TickerAppConfig(AppConfig): 5 | name = 'ticker_app' 6 | -------------------------------------------------------------------------------- /ticker_app/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.5 on 2017-09-29 08:29 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='ExchangeTicker', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('exchange_id', models.IntegerField()), 21 | ('pair_id', models.IntegerField()), 22 | ('high', models.DecimalField(decimal_places=15, max_digits=30)), 23 | ('last', models.DecimalField(decimal_places=15, max_digits=30)), 24 | ('low', models.DecimalField(decimal_places=15, max_digits=30)), 25 | ('bid', models.DecimalField(decimal_places=15, max_digits=30)), 26 | ('ask', models.DecimalField(decimal_places=15, max_digits=30)), 27 | ('base_volume', models.DecimalField(blank=True, decimal_places=15, max_digits=30, null=True)), 28 | ('percent_change', models.DecimalField(decimal_places=8, default=0, max_digits=10)), 29 | ('date_time', models.DateTimeField()), 30 | ], 31 | options={ 32 | 'verbose_name': 'Данные тикера', 33 | 'verbose_name_plural': 'Данные тикеров', 34 | }, 35 | ), 36 | ] 37 | -------------------------------------------------------------------------------- /ticker_app/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/ticker_app/migrations/__init__.py -------------------------------------------------------------------------------- /ticker_app/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from trade import models as trade_models 3 | 4 | 5 | # Create your models here. 6 | class ExchangeTicker(models.Model): 7 | exchange_id = models.IntegerField() 8 | pair_id = models.IntegerField() 9 | high = models.DecimalField(max_digits=30, decimal_places=15) 10 | last = models.DecimalField(max_digits=30, decimal_places=15) 11 | low = models.DecimalField(max_digits=30, decimal_places=15) 12 | bid = models.DecimalField(max_digits=30, decimal_places=15) 13 | ask = models.DecimalField(max_digits=30, decimal_places=15) 14 | base_volume = models.DecimalField(max_digits=30, decimal_places=15, null=True, blank=True) 15 | percent_change = models.DecimalField(max_digits=10, decimal_places=8, default=0) 16 | date_time = models.DateTimeField(blank=False, null=False) 17 | 18 | def __str__(self): 19 | # return trade_models.Exchanges.objects.get(pk=self.exchange_id).name + ': ' + self.pair.main_coin.symbol.upper() + '-' + self.pair.second_coin.symbol.upper() 20 | return '{}: {}'.format(self.exchange_id, self.pair_id) 21 | 22 | class Meta: 23 | verbose_name = 'Данные тикера' 24 | verbose_name_plural = 'Данные тикеров' 25 | -------------------------------------------------------------------------------- /ticker_app/routers.py: -------------------------------------------------------------------------------- 1 | class DBRouter: 2 | def db_for_read(self, model, **hints): 3 | if model._meta.app_label == 'ticker_app': 4 | return 'portal_ticker' 5 | return None 6 | 7 | def db_for_write(self, model, **hints): 8 | if model._meta.app_label == 'ticker_app': 9 | return 'portal_ticker' 10 | return None 11 | 12 | def allow_relation(self, obj1, obj2, **hints): 13 | if obj1._meta.app_label == 'ticker_app' and obj2._meta.app_label == 'ticker_app': 14 | return True 15 | elif 'ticker_app' not in [obj1._meta.app_label, obj2._meta.app_label]: 16 | return None 17 | return False 18 | 19 | def allow_migrate(self, db, app_label, model_name=None, **hints): 20 | if app_label == 'ticker_app': 21 | return db == 'portal_ticker' 22 | elif db == 'portal_ticker': 23 | return False 24 | return None 25 | 26 | 27 | class PrimaryRouter: 28 | def db_for_read(self, model, **hints): 29 | return 'default' 30 | 31 | def db_for_write(self, model, **hints): 32 | return 'default' 33 | 34 | def allow_relation(self, obj1, obj2, **hints): 35 | db_list = ('default',) 36 | if obj1._state.db in db_list and obj2._state.db in db_list: 37 | return True 38 | return None 39 | 40 | def allow_migrate(self, db, app_label, model_name=None, **hints): 41 | return True 42 | -------------------------------------------------------------------------------- /ticker_app/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /ticker_app/views.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.core.serializers.json import DjangoJSONEncoder 3 | from django.http import HttpResponse 4 | from .models import ExchangeTicker 5 | from django.utils import timezone 6 | import datetime 7 | from tradeBOT.models import Extremum 8 | import json 9 | 10 | 11 | def get_ticker(request): 12 | if request.is_ajax(): 13 | pair_id = request.POST.get('pair_id') 14 | intervale = int(request.POST.get('intervale')) 15 | zoom = request.POST.get('zoom') 16 | chart_data = {} 17 | ticker_list = [] 18 | extremums_list = [] 19 | intervales = [] 20 | if zoom == 'all': 21 | ticker = list(ExchangeTicker.objects.values('date_time', 'last').filter(pair_id=pair_id)) 22 | else: 23 | ticker = list(ExchangeTicker.objects.values('date_time', 'last').filter(pair_id=pair_id, 24 | date_time__gte=timezone.now() - datetime.timedelta( 25 | hours=int(zoom)))) 26 | if len(ticker) > 0: 27 | extremums = Extremum.objects.filter(pair_id=pair_id, 28 | date__gte=ticker[0]['date_time']) 29 | for item in extremums: 30 | extremums_list.append([item.date, item.price, item.ext_type]) 31 | s_date = ticker[0]['date_time'] 32 | while s_date < timezone.now(): 33 | intervales.append(s_date) 34 | s_date = s_date + datetime.timedelta(minutes=intervale) 35 | if len(intervales) > 0: 36 | s_date = intervales.pop(0) 37 | # print('От {} до {}'.format(s_date, s_date + datetime.timedelta(minutes=intervale))) 38 | s_chain = [x for x in ticker if 39 | s_date + datetime.timedelta(minutes=intervale) > x['date_time'] >= s_date] 40 | while len(intervales) > 0: 41 | try: 42 | ticker_list.append({'date': s_date, 43 | 'open': s_chain[0]['last'], 44 | 'close': s_chain[-1]['last'], 45 | 'low': min([x['last'] for x in s_chain]), 46 | 'high': max([x['last'] for x in s_chain])}) 47 | except IndexError: 48 | pass 49 | s_date = intervales.pop(0) 50 | # print('Новая от {} до {}'.format(s_date, s_date + datetime.timedelta(minutes=intervale))) 51 | s_chain = [x for x in ticker if 52 | s_date + datetime.timedelta(minutes=intervale) > x['date_time'] >= s_date] 53 | # print("Выборка {}".format(s_chain)) 54 | chart_data['ticker'] = ticker_list 55 | chart_data['extremums'] = extremums_list 56 | return HttpResponse(json.dumps(chart_data, cls=DjangoJSONEncoder), status=200) 57 | -------------------------------------------------------------------------------- /trade/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/__init__.py -------------------------------------------------------------------------------- /trade/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Exchanges, UserExchange, UserBalance, Coin, Wallets, UserWallet, UserHoldings, Transaction 3 | 4 | 5 | class TransactionAdmin(admin.ModelAdmin): 6 | list_display = ['name', 't_type', 'date', 'type', 'value'] 7 | 8 | class Meta: 9 | model = Transaction 10 | 11 | 12 | class UserBalancesAdmin(admin.ModelAdmin): 13 | list_display = [field.name for field in UserBalance._meta.fields] 14 | list_filter = ['ue'] 15 | 16 | class Meta: 17 | model = UserBalance 18 | 19 | 20 | admin.site.register(Exchanges) 21 | admin.site.register(UserExchange) 22 | admin.site.register(UserBalance, UserBalancesAdmin) 23 | admin.site.register(Coin) 24 | admin.site.register(Wallets) 25 | admin.site.register(Transaction, TransactionAdmin) 26 | admin.site.register(UserWallet) 27 | admin.site.register(UserHoldings) 28 | -------------------------------------------------------------------------------- /trade/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class TradeConfig(AppConfig): 5 | name = 'trade' 6 | -------------------------------------------------------------------------------- /trade/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms import ModelForm 2 | from trade.models import UserExchange, UserWallet 3 | from django.contrib.auth.models import User 4 | from django import forms 5 | from django.forms.extras.widgets import SelectDateWidget 6 | 7 | 8 | class UserWalletForm(ModelForm): 9 | class Meta: 10 | model = UserWallet 11 | fields = ['wallet', 'address'] 12 | 13 | 14 | class UserExchangesForm(ModelForm): 15 | class Meta: 16 | model = UserExchange 17 | fields = ['exchange', 'apikey', 'apisecret'] 18 | -------------------------------------------------------------------------------- /trade/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.5 on 2017-09-29 08:29 3 | from __future__ import unicode_literals 4 | 5 | from django.conf import settings 6 | from django.db import migrations, models 7 | import django.db.models.deletion 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | initial = True 13 | 14 | dependencies = [ 15 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 16 | ] 17 | 18 | operations = [ 19 | migrations.CreateModel( 20 | name='Coin', 21 | fields=[ 22 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 23 | ('short_name', models.CharField(max_length=20)), 24 | ('full_name', models.CharField(max_length=40)), 25 | ], 26 | options={ 27 | 'verbose_name': 'Криптовалюта', 28 | 'verbose_name_plural': 'Криптовалюты', 29 | }, 30 | ), 31 | migrations.CreateModel( 32 | name='Exchanges', 33 | fields=[ 34 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 35 | ('name', models.CharField(max_length=255)), 36 | ('info_frozen_key', models.CharField(max_length=31)), 37 | ], 38 | options={ 39 | 'verbose_name': 'Биржа', 40 | 'verbose_name_plural': 'Биржи', 41 | }, 42 | ), 43 | migrations.CreateModel( 44 | name='Transaction', 45 | fields=[ 46 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 47 | ('name', models.CharField(max_length=50)), 48 | ('t_type', models.CharField(max_length=20)), 49 | ('number', models.BigIntegerField()), 50 | ('date', models.DateTimeField()), 51 | ('t_from', models.TextField()), 52 | ('t_to', models.TextField()), 53 | ('type', models.CharField(max_length=10)), 54 | ('value', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 55 | ('block_hash', models.CharField(default=None, max_length=127, null=True)), 56 | ('hash', models.CharField(max_length=127)), 57 | ('comment', models.TextField(default='', null=True)), 58 | ('title', models.CharField(default='', max_length=255, null=True)), 59 | ('details', models.CharField(default='', max_length=255, null=True)), 60 | ('usd_value', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 61 | ('user_comment', models.CharField(blank=True, default=None, max_length=255, null=True)), 62 | ('currency', models.CharField(blank=True, default=None, max_length=10, null=True)), 63 | ], 64 | options={ 65 | 'verbose_name': 'Транзакциия', 66 | 'verbose_name_plural': 'Транзакции', 67 | }, 68 | ), 69 | migrations.CreateModel( 70 | name='UserBalance', 71 | fields=[ 72 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 73 | ('coin', models.CharField(max_length=10)), 74 | ('total', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 75 | ('used', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 76 | ('free', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 77 | ('conversions', models.CharField(max_length=255)), 78 | ('btc_value', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 79 | ('last_update', models.DateTimeField(auto_now=True)), 80 | ], 81 | options={ 82 | 'verbose_name': 'Баланс пользователя', 83 | 'verbose_name_plural': 'Балансы пользователей', 84 | }, 85 | ), 86 | migrations.CreateModel( 87 | name='UserExchange', 88 | fields=[ 89 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 90 | ('apikey', models.CharField(max_length=127)), 91 | ('apisecret', models.CharField(max_length=255)), 92 | ('is_active', models.BooleanField(default=False)), 93 | ('is_active_script', models.BooleanField(default=False)), 94 | ('is_correct', models.BooleanField(default=True)), 95 | ('total_btc', models.DecimalField(decimal_places=8, max_digits=30)), 96 | ('total_usd', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 97 | ('coefficient_of_depth', models.IntegerField(default=0)), 98 | ('error', models.CharField(blank=True, max_length=255)), 99 | ('exchange', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='trade.Exchanges')), 100 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 101 | ], 102 | options={ 103 | 'verbose_name': 'Биржа пользователя', 104 | 'verbose_name_plural': 'Биржи пользователей', 105 | }, 106 | ), 107 | migrations.CreateModel( 108 | name='UserHoldings', 109 | fields=[ 110 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 111 | ('type', models.CharField(max_length=255)), 112 | ('total_btc', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 113 | ('total_usd', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 114 | ('date_time', models.DateTimeField()), 115 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 116 | ], 117 | options={ 118 | 'verbose_name': 'История баланса', 119 | 'verbose_name_plural': 'Истории балансов', 120 | }, 121 | ), 122 | migrations.CreateModel( 123 | name='UserWallet', 124 | fields=[ 125 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 126 | ('address', models.CharField(max_length=511)), 127 | ('access_token', models.CharField(blank=True, default=None, max_length=511, null=True)), 128 | ('balance', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 129 | ('total_btc', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 130 | ('total_usd', models.DecimalField(decimal_places=8, default=0, max_digits=30)), 131 | ('last_update', models.DateTimeField(auto_now=True)), 132 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 133 | ], 134 | options={ 135 | 'verbose_name': 'Кошелёк пользователя', 136 | 'verbose_name_plural': 'Кошельки пользователей', 137 | }, 138 | ), 139 | migrations.CreateModel( 140 | name='Wallets', 141 | fields=[ 142 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 143 | ('name', models.CharField(max_length=255)), 144 | ], 145 | options={ 146 | 'verbose_name': 'Кошелёк', 147 | 'verbose_name_plural': 'Кошельки', 148 | }, 149 | ), 150 | migrations.AddField( 151 | model_name='userwallet', 152 | name='wallet', 153 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='trade.Wallets'), 154 | ), 155 | migrations.AddField( 156 | model_name='userbalance', 157 | name='ue', 158 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='trade.UserExchange'), 159 | ), 160 | migrations.AlterUniqueTogether( 161 | name='transaction', 162 | unique_together=set([('name', 't_type', 'hash')]), 163 | ), 164 | ] 165 | -------------------------------------------------------------------------------- /trade/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/migrations/__init__.py -------------------------------------------------------------------------------- /trade/models.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from decimal import Decimal 4 | from django.contrib.auth.models import User 5 | from django.db import models 6 | from pytz import utc 7 | import time 8 | 9 | 10 | class Exchanges(models.Model): 11 | name = models.CharField(max_length=255) 12 | info_frozen_key = models.CharField(max_length=31) 13 | 14 | def __str__(self): 15 | return self.name 16 | 17 | class Meta: 18 | verbose_name = "Биржа" 19 | verbose_name_plural = "Биржи" 20 | 21 | 22 | class UserExchange(models.Model): 23 | user = models.ForeignKey(User) 24 | exchange = models.ForeignKey(Exchanges) 25 | apikey = models.CharField(max_length=127) 26 | apisecret = models.CharField(max_length=255) 27 | is_active = models.BooleanField(default=False) 28 | is_active_script = models.BooleanField(default=False) 29 | is_correct = models.BooleanField(default=True) 30 | total_btc = models.DecimalField(max_digits=30, decimal_places=8) 31 | total_usd = models.DecimalField(max_digits=30, decimal_places=8, default=0) 32 | coefficient_of_depth = models.IntegerField(default=0) 33 | error = models.CharField(max_length=255, blank=True) 34 | 35 | def __str__(self): 36 | return self.user.username + ': ' + self.exchange.name + ' (' + str(self.pk) + ')' 37 | 38 | class Meta: 39 | verbose_name = "Биржа пользователя" 40 | verbose_name_plural = "Биржи пользователей" 41 | 42 | 43 | class UserBalance(models.Model): 44 | ue = models.ForeignKey(UserExchange) 45 | coin = models.CharField(max_length=10) 46 | total = models.DecimalField(max_digits=30, decimal_places=8, default=0) 47 | used = models.DecimalField(max_digits=30, decimal_places=8, default=0) 48 | free = models.DecimalField(max_digits=30, decimal_places=8, default=0) 49 | conversions = models.CharField(max_length=255) 50 | btc_value = models.DecimalField(max_digits=30, decimal_places=8, default=0) 51 | last_update = models.DateTimeField(auto_now=True) 52 | 53 | def __str__(self): 54 | return self.ue.exchange.name + ' ' + self.ue.user.username + ' ' + self.coin + ': ' + str(self.total) 55 | 56 | class Meta: 57 | verbose_name = "Баланс пользователя" 58 | verbose_name_plural = "Балансы пользователей" 59 | 60 | 61 | class Coin(models.Model): 62 | short_name = models.CharField(max_length=20) 63 | full_name = models.CharField(max_length=40) 64 | 65 | def __str__(self): 66 | return self.short_name + '-' + self.full_name 67 | 68 | class Meta: 69 | verbose_name = 'Криптовалюта' 70 | verbose_name_plural = 'Криптовалюты' 71 | 72 | 73 | class Wallets(models.Model): 74 | name = models.CharField(max_length=255) 75 | 76 | def __str__(self): 77 | return self.name 78 | 79 | class Meta: 80 | verbose_name = 'Кошелёк' 81 | verbose_name_plural = "Кошельки" 82 | 83 | 84 | class UserWallet(models.Model): 85 | user = models.ForeignKey(User) 86 | wallet = models.ForeignKey(Wallets) 87 | address = models.CharField(max_length=511) 88 | access_token = models.CharField(max_length=511, blank=True, default=None, null=True) 89 | balance = models.DecimalField(max_digits=30, decimal_places=8, default=0) 90 | total_btc = models.DecimalField(max_digits=30, decimal_places=8, default=0) 91 | total_usd = models.DecimalField(max_digits=30, decimal_places=8, default=0) 92 | last_update = models.DateTimeField(auto_now=True) 93 | 94 | def __str__(self): 95 | return '<' + self.user.username + ' ' + self.wallet.name + ': ' + str(self.balance) + '>' 96 | 97 | class Meta: 98 | verbose_name = 'Кошелёк пользователя' 99 | verbose_name_plural = 'Кошельки пользователей' 100 | 101 | 102 | class Transaction(models.Model): 103 | name = models.CharField(max_length=50) 104 | t_type = models.CharField(max_length=20) 105 | number = models.BigIntegerField(blank=False, null=False) 106 | date = models.DateTimeField(blank=False) 107 | t_from = models.TextField() 108 | t_to = models.TextField() 109 | type = models.CharField(max_length=10) 110 | value = models.DecimalField(max_digits=30, decimal_places=8, default=0) 111 | block_hash = models.CharField(max_length=127, default=None, null=True) 112 | hash = models.CharField(max_length=127) 113 | comment = models.TextField(default='', null=True) 114 | title = models.CharField(max_length=255, default='', null=True) 115 | details = models.CharField(max_length=255, default='', null=True) 116 | usd_value = models.DecimalField(max_digits=30, decimal_places=8, default=0) 117 | user_comment = models.CharField(max_length=255, blank=True, default=None, null=True) 118 | currency = models.CharField(max_length=10, blank=True, default=None, null=True) 119 | 120 | def __str__(self): 121 | return '<' + self.name + ' ' + self.type + ' ' + str(self.value) + '>' 122 | 123 | class Meta: 124 | verbose_name = 'Транзакциия' 125 | verbose_name_plural = 'Транзакции' 126 | unique_together = ('name', 't_type', 'hash') 127 | 128 | 129 | class UserHoldings(models.Model): 130 | user = models.ForeignKey(User) 131 | type = models.CharField(max_length=255) 132 | total_btc = models.DecimalField(max_digits=30, decimal_places=8, default=0) 133 | total_usd = models.DecimalField(max_digits=30, decimal_places=8, default=0) 134 | date_time = models.DateTimeField(blank=False) 135 | 136 | def __str__(self): 137 | return '<' + self.user.username + ' - ' + self.type + ': ' + str(self.total_btc) + '>' 138 | 139 | class Meta: 140 | verbose_name_plural = 'Истории балансов' 141 | verbose_name = 'История баланса' 142 | 143 | def as_list(self): 144 | return [ 145 | int(time.mktime(self.date_time.timetuple()) * 1000), 146 | float(Decimal(self.total_btc).quantize(Decimal('.00000001'))) 147 | ] 148 | -------------------------------------------------------------------------------- /trade/static/css/images/animated-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/animated-overlay.gif -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /trade/static/css/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/css/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /trade/static/css/jqChart.css: -------------------------------------------------------------------------------- 1 | .ui-jqchart { 2 | position: relative; 3 | } 4 | 5 | .ui-jqchart .ui-jqchart-toolbar { 6 | position: absolute; 7 | margin: 0; 8 | padding: 2px; 9 | list-style-type: none; 10 | white-space: nowrap; 11 | } 12 | 13 | .ui-jqchart .ui-jqchart-toolbar li { 14 | display: inline-block; 15 | vertical-align: top; 16 | margin: 0 2px; 17 | padding: 2px 0; 18 | cursor: pointer; 19 | } 20 | 21 | .ui-jqchart .ui-jqchart-toolbar span.ui-icon { 22 | float: left; 23 | margin: 0 2px; 24 | } 25 | 26 | .ui-jqchart .ui-jqchart-toolbar-separator { 27 | height: 16px; 28 | width: 1px; 29 | } 30 | 31 | .ui-jqchart .ui-jqchart-tooltip { 32 | position: absolute; 33 | white-space: nowrap; 34 | padding: .2em .4em; 35 | z-index: 9999; 36 | border: 1px solid #dddddd; 37 | color: #333333; 38 | background: white; 39 | -moz-border-radius: 4px; 40 | -webkit-border-radius: 4px; 41 | border-radius: 4px; 42 | -o-box-shadow: 0 0 5px #aaa; 43 | -moz-box-shadow: 0 0 5px #aaa; 44 | -webkit-box-shadow: 0 0 5px #aaa; 45 | box-shadow: 0 0 5px #aaa; 46 | } 47 | 48 | * html .ui-jqchart .ui-jqchart-tooltip { 49 | background-image: none; 50 | } 51 | 52 | body .ui-jqchart .ui-jqchart-tooltip { 53 | border-width: 2px; 54 | } -------------------------------------------------------------------------------- /trade/static/css/jqRangeSlider.css: -------------------------------------------------------------------------------- 1 | .ui-jqrangeslider { position: relative; } 2 | 3 | .ui-jqrangeslider .ui-jqrangeslider-arrow-left { position: absolute; width: 18px; cursor: pointer; vertical-align: middle; } 4 | .ui-jqrangeslider .ui-jqrangeslider-arrow-icon-left { position: absolute; } 5 | .ui-jqrangeslider .ui-jqrangeslider-arrow-right { position: absolute; width: 18px; cursor: pointer; } 6 | .ui-jqrangeslider .ui-jqrangeslider-arrow-icon-right { position: absolute; } 7 | .ui-jqrangeslider .ui-jqrangeslider-handle-left { position: absolute; width: 12px; cursor: ew-resize; } 8 | .ui-jqrangeslider .ui-jqrangeslider-handle-icon-left { position: absolute; } 9 | .ui-jqrangeslider .ui-jqrangeslider-handle-right { position: absolute; width: 12px; cursor: ew-resize; } 10 | .ui-jqrangeslider .ui-jqrangeslider-handle-icon-right { position: absolute; } 11 | .ui-jqrangeslider .ui-jqrangeslider-slider-horizontal { position: absolute; cursor: move; cursor: grab; cursor: -moz-grab; } 12 | .ui-jqrangeslider .ui-jqrangeslider-slider-horizontal-dragging { cursor: -moz-grabbing; cursor: grabbing; } 13 | .ui-jqrangeslider .ui-jqrangeslider-background-horizontal { position: absolute; } 14 | .ui-jqrangeslider .ui-jqrangeslider-background-horizontal-left { position: absolute; } 15 | .ui-jqrangeslider .ui-jqrangeslider-background-horizontal-right { position: absolute; } 16 | 17 | .ui-jqrangeslider .ui-jqrangeslider-arrow-bottom { position: absolute; height: 18px; cursor: pointer; } 18 | .ui-jqrangeslider .ui-jqrangeslider-arrow-icon-bottom { position: absolute; } 19 | .ui-jqrangeslider .ui-jqrangeslider-arrow-top { position: absolute; height: 18px; cursor: pointer; } 20 | .ui-jqrangeslider .ui-jqrangeslider-arrow-icon-top { position: absolute; } 21 | .ui-jqrangeslider .ui-jqrangeslider-handle-bottom { position: absolute; height: 12px; cursor: ns-resize; } 22 | .ui-jqrangeslider .ui-jqrangeslider-handle-icon-bottom { position: absolute; } 23 | .ui-jqrangeslider .ui-jqrangeslider-handle-top { position: absolute; height: 12px; cursor: ns-resize; } 24 | .ui-jqrangeslider .ui-jqrangeslider-handle-icon-top { position: absolute; } 25 | .ui-jqrangeslider .ui-jqrangeslider-slider-vertical { position: absolute; cursor: move; cursor: grab; cursor: -moz-grab; } 26 | .ui-jqrangeslider .ui-jqrangeslider-slider-vertical-dragging { cursor: -moz-grabbing; cursor: grabbing; } 27 | .ui-jqrangeslider .ui-jqrangeslider-background-vertical { position: absolute; } 28 | .ui-jqrangeslider .ui-jqrangeslider-background-vertical-bottom { position: absolute; } 29 | .ui-jqrangeslider .ui-jqrangeslider-background-vertical-top { position: absolute; } -------------------------------------------------------------------------------- /trade/static/css/setup.css: -------------------------------------------------------------------------------- 1 | .chart-info { 2 | font-size: 0.8rem; 3 | min-width: 50%; 4 | float: right; 5 | display: flex; 6 | display: -webkit-flex; 7 | -webkit-justify-content: space-around; 8 | justify-content: space-around; 9 | } 10 | 11 | .btn-mini { 12 | padding: 1px 6px; 13 | height: 20px; 14 | line-height: 20px; 15 | } 16 | 17 | .graph-block, .order_table { 18 | border: 1px slategrey solid; 19 | background: #fafafa; 20 | } 21 | 22 | .exchange-coins-block { 23 | max-height: 600px; 24 | border: 1px slategrey solid; 25 | background: #fafafa; 26 | } 27 | 28 | .exchange-coins-block-scroll { 29 | overflow-y: scroll; 30 | max-height: 390px; 31 | font-size: 10px; 32 | } 33 | 34 | .header h5 { 35 | margin-top: 0 !important; 36 | } 37 | 38 | .header { 39 | padding: 10px 0 4px 0; 40 | } 41 | 42 | .directions_block { 43 | width: 100%; 44 | height: 300px; 45 | overflow-x: scroll; 46 | } 47 | 48 | .priceChangeUp { 49 | background-color: #ceebd3 !important; 50 | border-top: 1px double #27892f; 51 | border-bottom: 1px double #27892f; 52 | -webkit-transition: all .3s; 53 | -moz-transition: all .3s; 54 | -ms-transition: all .3s; 55 | -o-transition: all .3s; 56 | transition: all .3s; 57 | } 58 | 59 | .priceChangeDown { 60 | background-color: #f6d4d1 !important; 61 | border-top: 1px double #c02a1d; 62 | border-bottom: 1px double #c02a1d; 63 | -webkit-transition: all .3s; 64 | -moz-transition: all .3s; 65 | -ms-transition: all .3s; 66 | -o-transition: all .3s; 67 | transition: all .3s; 68 | } 69 | 70 | #buttons-zoom button, #buttons button { 71 | margin: -2px; 72 | border-radius: 0; 73 | background-image: linear-gradient(#ffffff, #c4d5db); 74 | background-color: white; 75 | box-shadow: none; 76 | border: 1px solid #91abac; 77 | color: black; 78 | border-left-width: 0; 79 | font-size: 11px; 80 | } 81 | 82 | #buttons-zoom div button:first-child, #buttons div button:first-child { 83 | border-top-left-radius: 10px; 84 | border-bottom-left-radius: 10px; 85 | } 86 | 87 | #buttons-zoom div button:last-child, #buttons div button:last-child { 88 | border-top-right-radius: 10px; 89 | border-bottom-right-radius: 10px; 90 | } 91 | 92 | .ui-jqchart-toolbar.ui-widget.ui-widget-content.ui-corner-all { 93 | position: absolute; 94 | right: 100px !important; 95 | left: auto !important; 96 | } -------------------------------------------------------------------------------- /trade/static/css/style.css: -------------------------------------------------------------------------------- 1 | .main-nav { 2 | background: #388e3c; 3 | } 4 | 5 | .main-nav li { 6 | border-left: 1px solid #2e7d32; 7 | border-right: 1px solid #1b5e20; 8 | font-weight: bold; 9 | text-transform: uppercase; 10 | font-size: 14px; 11 | } 12 | 13 | .main-nav li:first-child { 14 | border-left: 1px solid #2e7d32; 15 | } 16 | 17 | .main-nav li a { 18 | color: lightgray; 19 | } 20 | 21 | .brand-logo img { 22 | margin: 0 auto; 23 | padding: 10px; 24 | } 25 | 26 | .exchange { 27 | width: 100%; 28 | text-align: center; 29 | } 30 | 31 | 32 | .exchange th { 33 | border: none; 34 | color: #1e2324; 35 | text-align: center; 36 | background: #a5d6a7; 37 | font-weight: bolder; 38 | } 39 | .user_coins td { 40 | border-bottom: 1px solid #e8e0e0; 41 | } 42 | 43 | .workers { 44 | width: 100%; 45 | text-align: center; 46 | } 47 | 48 | .workers td{ 49 | border-left: 1px solid gray; 50 | border-bottom: 1px solid gray; 51 | } 52 | 53 | .workers td:last-child{ 54 | border-right: 1px solid gray; 55 | } 56 | 57 | 58 | .workers th { 59 | border: none; 60 | color: #1e2324; 61 | text-align: center; 62 | background: #a5d6a7; 63 | font-weight: bolder; 64 | } 65 | 66 | .user_coins td:first-child { 67 | font-weight: bolder; 68 | text-align: left; 69 | text-transform: uppercase; 70 | } 71 | 72 | tr.balances td:last-child { 73 | text-align: right; 74 | } 75 | 76 | .mysize { 77 | font-size: 1.5rem !important; 78 | } 79 | 80 | .exchange-header th:nth-child(1) { 81 | width: 10% !important; 82 | } 83 | 84 | .main-content { 85 | margin-top: 30px; 86 | padding: 48px 0 48px 0; 87 | background-color: #e5f0e6; 88 | min-height: 200px; 89 | } 90 | 91 | .user-info { 92 | border-right: 1px solid lightgray; 93 | } 94 | 95 | .totalBTC { 96 | font-family: Roboto, serif; 97 | font-size: xx-large; 98 | display: block; 99 | text-align: center; 100 | } 101 | 102 | .wallet { 103 | padding: 20px; 104 | margin-bottom: 50px; 105 | background: #b3d5d6; 106 | } 107 | 108 | .transactions-table { 109 | max-width: 100%; 110 | width: 100%; 111 | } 112 | 113 | .transactions-table thead th { 114 | background: #009688; 115 | color: white; 116 | } 117 | 118 | .transactions-table tbody td { 119 | border-bottom: 1px solid grey; 120 | } 121 | 122 | .transactions-table tbody td:last-child { 123 | word-break: break-all; 124 | } 125 | 126 | .transaction-type { 127 | padding: 2px; 128 | border-radius: 2px; 129 | } 130 | 131 | .table-bordered { 132 | border: 1px solid #c7ecb8; 133 | border-collapse: separate; 134 | *border-collapse: collapsed; 135 | border-left: 0; 136 | -webkit-border-radius: 4px; 137 | -moz-border-radius: 4px; 138 | border-radius: 4px; 139 | } 140 | 141 | .table-bordered th, 142 | .table-bordered td { 143 | border-bottom: 1px solid #c7ecb8; 144 | } 145 | 146 | .fa-commenting { 147 | cursor: pointer; 148 | } 149 | 150 | .alert-new { 151 | padding: 10px; 152 | font-weight: bold; 153 | border-radius: 4px; 154 | font-size: 1.1rem; 155 | margin: 0 0 2em 0; 156 | } 157 | 158 | .transaction-info td { 159 | border-bottom: 1px solid grey; 160 | } 161 | 162 | .transaction-info { 163 | color: black; 164 | background: white; 165 | border: 1px solid white; 166 | text-align: left !important; 167 | } 168 | 169 | .second-nav { 170 | height: 26px; 171 | line-height: 26px; 172 | } 173 | 174 | .exchange-coins { 175 | border: 1px solid grey; 176 | width: 80%; 177 | border-spacing: 0; 178 | } 179 | 180 | .exchange-coins td { 181 | height: 30px; 182 | line-height: 30px; 183 | border-bottom: 1px solid grey 184 | } 185 | 186 | .exchange-coins td i { 187 | cursor: pointer; 188 | } 189 | 190 | .rank-up, .rank-down, .primary-rank { 191 | padding: 3px 5px; 192 | color: white; 193 | } 194 | 195 | .pair { 196 | background: #4caf50; 197 | } 198 | 199 | .unactive { 200 | background: #f44336 !important; 201 | } 202 | 203 | .pair-share { 204 | width: 80%; 205 | } 206 | 207 | .primary-coins { 208 | display: -webkit-flex; 209 | display: flex; 210 | -webkit-justify-content: space-around; 211 | justify-content: space-around; 212 | -webkit-flex-wrap: wrap; 213 | flex-wrap: wrap; 214 | } 215 | 216 | .primary-coin { 217 | width: 50%; 218 | text-align: center; 219 | padding: 10px; 220 | } 221 | 222 | .primary-rank { 223 | display: none !important; 224 | cursor: pointer; 225 | } 226 | 227 | .rank:hover .primary-rank { 228 | display: inline !important; 229 | } 230 | 231 | .border { 232 | border: 1px solid red; 233 | } 234 | 235 | ::-webkit-scrollbar { 236 | width: 3px; 237 | } 238 | 239 | #buttons, #buttons-zoom { 240 | padding: 10px; 241 | } 242 | 243 | .ui-jqchart-tooltip { 244 | background: white; 245 | color: black; 246 | padding: 10px; 247 | border-radius: 10px; 248 | z-index: 10; 249 | border: 1px solid black; 250 | } 251 | 252 | .coinmarketcap-currency-widget div { 253 | border-radius: 0 !important; 254 | } 255 | .coinmarketcap-currency-widget > div > div:last-child { 256 | opacity: 0; 257 | height: 0 !important; 258 | padding: 0 !important; 259 | } 260 | 261 | .pair-advanced { 262 | padding-bottom: 10px; 263 | } 264 | 265 | .pair-advanced input { 266 | width: 100px; 267 | } 268 | 269 | .active_pair { 270 | background-image: linear-gradient(#ebdf95, #fbf4c7 15%); 271 | border-right: 0; 272 | border-left: 0; 273 | } 274 | 275 | .active_pair td { 276 | border-top: 1px solid #f7ab1c !important; 277 | border-bottom: 1px solid #f7ab1c !important; 278 | } 279 | 280 | .pair_tr td{ 281 | -webkit-transition: all .3s; 282 | -moz-transition: all .3s; 283 | -ms-transition: all .3s; 284 | -o-transition: all .3s; 285 | transition: all .3s; 286 | } 287 | 288 | .orders td { 289 | font-size: 10px; 290 | padding: 0 !important; 291 | } -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Bold.woff -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Bold.woff2 -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Light.woff -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Light.woff2 -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Medium.woff -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Medium.woff2 -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Regular.woff -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Thin.woff -------------------------------------------------------------------------------- /trade/static/fonts/roboto/Roboto-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/fonts/roboto/Roboto-Thin.woff2 -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/ardor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/ardor.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/augur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/augur.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/bitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/bitcoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/bitcoindark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/bitcoindark.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/bitconnect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/bitconnect.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/bitshares.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/bitshares.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/blackcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/blackcoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/blocknet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/blocknet.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/bytecoin-bcn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/bytecoin-bcn.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/counterparty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/counterparty.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/dash.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/decred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/decred.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/digibyte.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/digibyte.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/dogecoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/dogecoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/ethereum-classic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/ethereum-classic.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/ethereum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/ethereum.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/etheroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/etheroll.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/factom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/factom.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/gamecredits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/gamecredits.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/gnosis-gno.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/gnosis-gno.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/golem-network-tokens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/golem-network-tokens.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/library-credit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/library-credit.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/lisk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/lisk.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/litecoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/litecoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/maidsafecoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/maidsafecoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/monero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/monero.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/namecoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/namecoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/nem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/nem.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/nxt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/nxt.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/peercoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/peercoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/potcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/potcoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/reddcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/reddcoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/ripple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/ripple.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/siacoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/siacoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/steem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/steem.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/stratis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/stratis.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/syscoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/syscoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/tether.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/tether.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/viacoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/viacoin.png -------------------------------------------------------------------------------- /trade/static/images/cryptotokens/zcash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/cryptotokens/zcash.png -------------------------------------------------------------------------------- /trade/static/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/images/logo.png -------------------------------------------------------------------------------- /trade/static/js/coinmarketcup.js: -------------------------------------------------------------------------------- 1 | !function(){var e;if(void 0===window.jQuery||"1.11.1"!==window.jQuery.fn.jquery){var t=document.createElement("script");t.setAttribute("type","text/javascript"),t.setAttribute("src","https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"),t.readyState?t.onreadystatechange=function(){"complete"!=this.readyState&&"loaded"!=this.readyState||a()}:t.onload=a,(document.getElementsByTagName("head")[0]||document.documentElement).appendChild(t)}else e=window.jQuery,n();function a(){e=window.jQuery.noConflict(!0),n()}function i(e){var t=" "+document.cookie,a=" "+e+"=",i=null,n=0,r=0;return t.length>0&&-1!=(n=t.indexOf(a))&&(n+=a.length,-1==(r=t.indexOf(";",n))&&(r=t.length),i=unescape(t.substring(n,r))),i}function n(){var t,a,n=(t=i("_locale")||void 0,a=!("object"!=typeof Intl||!Intl||"function"!=typeof Intl.NumberFormat),{toLocaleString:function(e,i){var n=Number(e);if(isNaN(n))return e;var r,o,c,l,s=i&&i.minDecimalPlaces,d=i&&i.maxDecimalPlaces;return void 0===s||void 0===d?(r=n,a?r.toLocaleString(t):r.toLocaleString()):(o=n,c=s,l=d,a?o.toLocaleString(t,{minimumFractionDigits:c,maximumFractionDigits:l}):o.toFixed(l))}});function r(e,t){var a=t;t=Math.pow(10,t);for(var i=["K","M","B","T"],r=i.length-1;r>=0;r--){var o=Math.pow(10,3*(r+1));if(o<=e){1e3==(e=Math.round(e*t/o)/t)&&r=1e3?n.toLocaleString(Math.round(e)):e>=1?n.toLocaleString(e,{minDecimalPlaces:8,maxDecimalPlaces:8}):e<1e-8?Number(e).toExponential(4):n.toLocaleString(e,{minDecimalPlaces:8,maxDecimalPlaces:8});return e}(e):function(e){e=e>=1?e>=1e5?n.toLocaleString(Math.round(e)):n.toLocaleString(e,{minDecimalPlaces:2,maxDecimalPlaces:2}):e<1e-6?Number(e).toExponential(2):n.toLocaleString(e,{minDecimalPlaces:6,maxDecimalPlaces:6});return e}(e)}function c(e,t,a){var i=t,n={btc:"аёї",usd:"$",eur:"€",cny:"ВҐ",gbp:"ВЈ",cad:"$",rub:"",hkd:"$",jpy:"ВҐ",aud:"$",brl:"R$",inr:"в‚№",krw:"в‚©",mxn:"$",idr:"Rp",chf:"Fr"};return e.toLowerCase()in n&&(i=n[e.toLowerCase()]+i),a&&(i=i+' '+e.toUpperCase()+""),i}function l(e,t,a,i,l,s,d,p,m,u,h,g,v,f,x,y,b,w){var L=w?"https://s2.coinmarketcap.com/static/img/coins/64x64/"+w+".png":"https://files.coinmarketcap.com/static/widget/coins_legacy/64x64/"+e+".png",k="#093";m<0&&(k="#d14836"),m=n.toLocaleString(m,{minDecimalPlaces:2,maxDecimalPlaces:2}),valTickerHTML=v?"("+a+")":"",valPrice=s?o(s,i):"?",valPercentHTML=m?'('+m+"%)":"",valMarketCap=u?r(u,2):"?",valVolume=h?r(h,2):"?",d?(mainLineHeight=25,valPriceSecondary=p?o(p,d):"?",secondaryHTML='
'+valPriceSecondary+" "+d+" "):(mainLineHeight=30,secondaryHTML="");var E="utm_medium=widget&utm_campaign=cmcwidget&utm_source="+location.hostname+"&utm_content="+e,P='
'+t+" "+valTickerHTML+'
'+valPrice+" "+i+" "+valPercentHTML+" "+secondaryHTML+'
';return P+=function(e,t,a,i,n,r,o,l){var s=0,d=0,p="",m="",u="";if(e&&s++,t&&s++,a&&s++,0==s)return"";1==s&&(d=100),2==s&&(d=49.8),3==s&&(d=33),e&&(borderWidth=0,(a||t)&&(borderWidth=1),p='
RANK

'+r+"
");a&&(borderWidth=0,t&&(borderWidth=1),m='
MARKET CAP

'+c(n,o,i)+"
");t&&(u='
VOLUME (24H)

'+c(n,l,i)+"
");return detailedHTML='
'+p+m+u+"
",detailedHTML}(f,x,y,b,l,g,valMarketCap,valVolume),P+='
Powered by CoinMarketCap
'}e(document).ready(function(e){e(".coinmarketcap-currency-widget").each(function(){var t=e(this).attr("data-currency"),a=e(this).data("currencyid"),i=e(this).attr("data-base").toUpperCase(),n=e(this).attr("data-secondary");n="BTC"==(n=n?n.toUpperCase():null)||"USD"==n?n:null;var r=e(this).attr("data-stats");r=(r=r?r.toUpperCase():null)==i?i:"USD";var o,c,s=!1!==e(this).data("ticker"),d=!1!==e(this).data("rank"),p=!1!==e(this).data("marketcap"),m=!1!==e(this).data("volume"),u=!1!==e(this).data("statsticker"),h=this;a?(o="https://widgets.coinmarketcap.com/v2/ticker/"+a+"/?ref=widget&convert="+i,c="volume_24h_"):(o="https://widgets.coinmarketcap.com/v1/ticker/"+t+"/?ref=widget&convert="+i,c="24h_volume_"),e.get({url:o,success:function(o){o=o.length?o[0]:o.data,t||(t=o.website_slug);var g="price_"+i.toLowerCase(),v=n?"price_"+n.toLowerCase():null,f="market_cap_"+r.toLowerCase(),x=c+r.toLowerCase(),y=parseFloat(o[g]),b=v?parseFloat(o[v]):null,w=parseInt(o[f]),L=parseInt(o[x]),k=o.name,E=o.symbol,P=Number(o.percent_change_24h),M=o.rank,C=l(t,k,E,i,r,y,n,b,P,w,L,M,s,d,m,p,u,a);e(h).html(C),e(h).find("a").css({"text-decoration":"none",color:"#428bca"})}})})})}}(); 2 | -------------------------------------------------------------------------------- /trade/static/js/exporting.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v5.0.12 (2017-05-24) 3 | Exporting module 4 | 5 | (c) 2010-2017 Torstein Honsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(p){"object"===typeof module&&module.exports?module.exports=p:p(Highcharts)})(function(p){(function(e){var p=e.defaultOptions,t=e.doc,B=e.Chart,u=e.addEvent,K=e.removeEvent,H=e.fireEvent,n=e.createElement,D=e.discardElement,I=e.css,x=e.merge,E=e.pick,k=e.each,F=e.objectEach,y=e.extend,z=e.win,J=z.navigator.userAgent,G=e.SVGRenderer,L=e.Renderer.prototype.symbols,M=/Edge\/|Trident\/|MSIE /.test(J),N=/firefox/i.test(J);y(p.lang,{printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image", 10 | downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",contextButtonTitle:"Chart context menu"});p.navigation={buttonOptions:{theme:{},symbolSize:14,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,verticalAlign:"top",width:24}};p.exporting={type:"image/png",url:"https://export.highcharts.com/",printMaxWidth:780,scale:2,buttons:{contextButton:{className:"highcharts-contextbutton",menuClassName:"highcharts-contextmenu",symbol:"menu",_titleKey:"contextButtonTitle", 11 | menuItems:[{textKey:"printChart",onclick:function(){this.print()}},{separator:!0},{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]}}};e.post=function(a,b,c){var d=n("form",x({method:"post",action:a,enctype:"multipart/form-data"},c), 12 | {display:"none"},t.body);F(b,function(a,b){n("input",{type:"hidden",name:b,value:a},null,d)});d.submit();D(d)};y(B.prototype,{sanitizeSVG:function(a,b){if(b&&b.exporting&&b.exporting.allowHTML){var c=a.match(/<\/svg>(.*?$)/);c&&c[1]&&(c='\x3cforeignObject x\x3d"0" y\x3d"0" width\x3d"'+b.chart.width+'" height\x3d"'+b.chart.height+'"\x3e\x3cbody xmlns\x3d"http://www.w3.org/1999/xhtml"\x3e'+c[1]+"\x3c/body\x3e\x3c/foreignObject\x3e",a=a.replace("\x3c/svg\x3e",c+"\x3c/svg\x3e"))}return a=a.replace(/zIndex="[^"]+"/g, 13 | "").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\(("|")(\S+)("|")\)/g,"url($2)").replace(/url\([^#]+#/g,"url(#").replace(/.*?$/,"\x3c/svg\x3e").replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g,'$1\x3d"rgb($2)" $1-opacity\x3d"$3"').replace(/ /g, 14 | "\u00a0").replace(/­/g,"\u00ad")},getChartHTML:function(){this.inlineStyles();return this.container.innerHTML},getSVG:function(a){var b,c,d,v,l,g=x(this.options,a);t.createElementNS||(t.createElementNS=function(a,b){return t.createElement(b)});c=n("div",null,{position:"absolute",top:"-9999em",width:this.chartWidth+"px",height:this.chartHeight+"px"},t.body);d=this.renderTo.style.width;l=this.renderTo.style.height;d=g.exporting.sourceWidth||g.chart.width||/px$/.test(d)&&parseInt(d,10)||600;l=g.exporting.sourceHeight|| 15 | g.chart.height||/px$/.test(l)&&parseInt(l,10)||400;y(g.chart,{animation:!1,renderTo:c,forExport:!0,renderer:"SVGRenderer",width:d,height:l});g.exporting.enabled=!1;delete g.data;g.series=[];k(this.series,function(a){v=x(a.userOptions,{animation:!1,enableMouseTracking:!1,showCheckbox:!1,visible:a.visible});v.isInternal||g.series.push(v)});k(this.axes,function(a){a.userOptions.internalKey||(a.userOptions.internalKey=e.uniqueKey())});b=new e.Chart(g,this.callback);a&&k(["xAxis","yAxis","series"],function(d){var c= 16 | {};a[d]&&(c[d]=a[d],b.update(c))});k(this.axes,function(a){var d=e.find(b.axes,function(b){return b.options.internalKey===a.userOptions.internalKey}),c=a.getExtremes(),f=c.userMin,c=c.userMax;!d||void 0===f&&void 0===c||d.setExtremes(f,c,!0,!1)});d=b.getChartHTML();d=this.sanitizeSVG(d,g);g=null;b.destroy();D(c);return d},getSVGForExport:function(a,b){var c=this.options.exporting;return this.getSVG(x({chart:{borderRadius:0}},c.chartOptions,b,{exporting:{sourceWidth:a&&a.sourceWidth||c.sourceWidth, 17 | sourceHeight:a&&a.sourceHeight||c.sourceHeight}}))},exportChart:function(a,b){b=this.getSVGForExport(a,b);a=x(this.options.exporting,a);e.post(a.url,{filename:a.filename||"chart",type:a.type,width:a.width||0,scale:a.scale,svg:b},a.formAttributes)},print:function(){var a=this,b=a.container,c=[],d=b.parentNode,e=t.body,l=e.childNodes,g=a.options.exporting.printMaxWidth,f,m;if(!a.isPrinting){a.isPrinting=!0;a.pointer.reset(null,0);H(a,"beforePrint");if(m=g&&a.chartWidth>g)f=[a.options.chart.width,void 0, 18 | !1],a.setSize(g,void 0,!1);k(l,function(a,b){1===a.nodeType&&(c[b]=a.style.display,a.style.display="none")});e.appendChild(b);z.focus();z.print();setTimeout(function(){d.appendChild(b);k(l,function(a,b){1===a.nodeType&&(a.style.display=c[b])});a.isPrinting=!1;m&&a.setSize.apply(a,f);H(a,"afterPrint")},1E3)}},contextMenu:function(a,b,c,d,e,l,g){var f=this,m=f.chartWidth,q=f.chartHeight,v="cache-"+a,h=f[v],r=Math.max(e,l),C,w;h||(f[v]=h=n("div",{className:a},{position:"absolute",zIndex:1E3,padding:r+ 19 | "px"},f.container),C=n("div",{className:"highcharts-menu"},null,h),w=function(){I(h,{display:"none"});g&&g.setState(0);f.openMenu=!1},f.exportEvents.push(u(h,"mouseleave",function(){h.hideTimer=setTimeout(w,500)}),u(h,"mouseenter",function(){clearTimeout(h.hideTimer)}),u(t,"mouseup",function(b){f.pointer.inClass(b.target,a)||w()})),k(b,function(a){if(a){var b;b=a.separator?n("hr",null,null,C):n("div",{className:"highcharts-menu-item",onclick:function(b){b&&b.stopPropagation();w();a.onclick&&a.onclick.apply(f, 20 | arguments)},innerHTML:a.text||f.options.lang[a.textKey]},null,C);f.exportDivElements.push(b)}}),f.exportDivElements.push(C,h),f.exportMenuWidth=h.offsetWidth,f.exportMenuHeight=h.offsetHeight);b={display:"block"};c+f.exportMenuWidth>m?b.right=m-c-e-r+"px":b.left=c-r+"px";d+l+f.exportMenuHeight>q&&"top"!==g.alignOptions.verticalAlign?b.bottom=q-d-r+"px":b.top=d+l-r+"px";I(h,b);f.openMenu=!0},addButton:function(a){var b=this,c=b.renderer,d=x(b.options.navigation.buttonOptions,a),e=d.onclick,l=d.menuItems, 21 | g,f,m=d.symbolSize||12;b.btnCount||(b.btnCount=0);b.exportDivElements||(b.exportDivElements=[],b.exportSVGElements=[]);if(!1!==d.enabled){var q=d.theme,k=q.states,h=k&&k.hover,k=k&&k.select,r;delete q.states;e?r=function(a){a.stopPropagation();e.call(b,a)}:l&&(r=function(){b.contextMenu(f.menuClassName,l,f.translateX,f.translateY,f.width,f.height,f);f.setState(2)});d.text&&d.symbol?q.paddingLeft=E(q.paddingLeft,25):d.text||y(q,{width:d.width,height:d.height,padding:0});f=c.button(d.text,0,0,r,q,h, 22 | k).addClass(a.className).attr({title:b.options.lang[d._titleKey],zIndex:3});f.menuClassName=a.menuClassName||"highcharts-menu-"+b.btnCount++;d.symbol&&(g=c.symbol(d.symbol,d.symbolX-m/2,d.symbolY-m/2,m,m).addClass("highcharts-button-symbol").attr({zIndex:1}).add(f));f.add().align(y(d,{width:f.width,x:E(d.x,b.buttonOffset)}),!0,"spacingBox");b.buttonOffset+=(f.width+d.buttonSpacing)*("right"===d.align?-1:1);b.exportSVGElements.push(f,g)}},destroyExport:function(a){var b=a?a.target:this;a=b.exportSVGElements; 23 | var c=b.exportDivElements,d=b.exportEvents,e;a&&(k(a,function(a,d){a&&(a.onclick=a.ontouchstart=null,e="cache-"+a.menuClassName,b[e]&&delete b[e],b.exportSVGElements[d]=a.destroy())}),a.length=0);c&&(k(c,function(a,d){clearTimeout(a.hideTimer);K(a,"mouseleave");b.exportDivElements[d]=a.onmouseout=a.onmouseover=a.ontouchstart=a.onclick=null;D(a)}),c.length=0);d&&(k(d,function(a){a()}),d.length=0)}});G.prototype.inlineToAttributes="fill stroke strokeLinecap strokeLinejoin strokeWidth textAnchor x y".split(" "); 24 | G.prototype.inlineBlacklist=[/-/,/^(clipPath|cssText|d|height|width)$/,/^font$/,/[lL]ogical(Width|Height)$/,/perspective/,/TapHighlightColor/,/^transition/];G.prototype.unstyledElements=["clipPath","defs","desc"];B.prototype.inlineStyles=function(){function a(a){return a.replace(/([A-Z])/g,function(a,b){return"-"+b.toLowerCase()})}function b(c){function q(b,e){n=u=!1;if(l){for(A=l.length;A--&&!u;)u=l[A].test(e);n=!u}"transform"===e&&"none"===b&&(n=!0);for(A=v.length;A--&&!n;)n=v[A].test(e)||"function"=== 25 | typeof b;n||r[e]!==b&&f[c.nodeName][e]!==b&&(-1!==d.indexOf(e)?c.setAttribute(a(e),b):p+=a(e)+":"+b+";")}var h,r,p="",w,n,u,A;if(1===c.nodeType&&-1===g.indexOf(c.nodeName)){h=z.getComputedStyle(c,null);r="svg"===c.nodeName?{}:z.getComputedStyle(c.parentNode,null);f[c.nodeName]||(m||(m=t.createElementNS(e.SVG_NS,"svg"),m.setAttribute("version","1.1"),t.body.appendChild(m)),w=t.createElementNS(c.namespaceURI,c.nodeName),m.appendChild(w),f[c.nodeName]=x(z.getComputedStyle(w,null)),m.removeChild(w)); 26 | if(N||M)for(var y in h)q(h[y],y);else F(h,q);p&&(h=c.getAttribute("style"),c.setAttribute("style",(h?h+";":"")+p));"svg"===c.nodeName&&c.setAttribute("stroke-width","1px");"text"!==c.nodeName&&k(c.children||c.childNodes,b)}}var c=this.renderer,d=c.inlineToAttributes,v=c.inlineBlacklist,l=c.inlineWhitelist,g=c.unstyledElements,f={},m;b(this.container.querySelector("svg"));m.parentNode.removeChild(m)};L.menu=function(a,b,c,d){return["M",a,b+2.5,"L",a+c,b+2.5,"M",a,b+d/2+.5,"L",a+c,b+d/2+.5,"M",a,b+ 27 | d-1.5,"L",a+c,b+d-1.5]};B.prototype.renderExporting=function(){var a=this,b=a.options.exporting,c=b.buttons,d=a.isDirtyExporting||!a.exportSVGElements;a.buttonOffset=0;a.isDirtyExporting&&a.destroyExport();d&&!1!==b.enabled&&(a.exportEvents=[],F(c,function(b){a.addButton(b)}),a.isDirtyExporting=!1);u(a,"destroy",a.destroyExport)};B.prototype.callbacks.push(function(a){a.renderExporting();u(a,"redraw",a.renderExporting);k(["exporting","navigation"],function(b){a[b]={update:function(c,d){a.isDirtyExporting= 28 | !0;x(!0,a.options[b],c);E(d,!0)&&a.redraw()}}})})})(p)}); 29 | -------------------------------------------------------------------------------- /trade/static/js/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('select').material_select(); 3 | $('.modal').modal(); 4 | $('#yandex-wallet-add').hide(); 5 | 6 | $('.input-field select').addClass('material'); 7 | 8 | $('.change_status').on('click', function () { 9 | var ue = $(this).parent('form').find('input[name="user-exchange"]').val(); 10 | var csrf = getCookie('csrftoken'); 11 | $.ajax({ 12 | url: '/change_status/', 13 | type: 'post', 14 | cache: !1, 15 | dataType: 'html', 16 | data: { 17 | ue: ue, 18 | csrfmiddlewaretoken: csrf 19 | }, 20 | success: function (data) { 21 | data === 'ok' ? location.reload() : data === '{"location": "/change_status/"}' ? Materialize.toast('У Вас недостаточно прав', 2000) : Materialize.toast('Не удалось изменить статус', 2000); 22 | } 23 | }); 24 | return false; 25 | }); 26 | $('.api-incorrect').on('click', function () { 27 | Materialize.toast('Api Key/Secret is incorrect', 2000); 28 | return false; 29 | }); 30 | $('#hidenull').on('click', function () { 31 | var hide = $(this).prop('checked'); 32 | hide0balances(hide); 33 | }); 34 | function hide0balances(hide) { 35 | if (hide) { 36 | for (var i = 0; i < $('.balance').length; i++) { 37 | var balance = $('.balance:eq(' + i + ')'); 38 | if (parseFloat(balance.text().replace(",", ".")) == 0) { 39 | balance.parent('tr').hide(); 40 | } 41 | } 42 | } else { 43 | $('.balances').show(); 44 | } 45 | } 46 | 47 | $('#wallet').find('select').on('change', function () { 48 | var wallet = $("#wallet").find("select option:selected").text(); 49 | if (wallet === 'Yandex Money') { 50 | $('#wallet').find('input#id_address').attr('disabled', true); 51 | $('#yandex-wallet-add').show(); 52 | $('#add-wallet-but').text('Продолжить') 53 | } else { 54 | $('#yandex-wallet-add').hide(); 55 | $('#wallet').find('input#id_address').attr('disabled', false); 56 | $('#add-wallet-but').text('Отправить') 57 | } 58 | }); 59 | 60 | $('.fa-commenting').on('click', function () { 61 | $('#user_comment_modal').modal('open'); 62 | $('input[name="tr_id"]').val($(this).attr('data-id')); 63 | }); 64 | $('#comment-form').on('submit', function () { 65 | var f = $(this).serializeArray(); 66 | $('i#trans' + f[1].value).parent('td').html(f[2].value); 67 | $.ajax({ 68 | url: '/transaction/new_comment/', 69 | type: 'post', 70 | dataType: 'html', 71 | data: f, 72 | success: function (q) { 73 | if ('ok' === q) { 74 | $('#user_comment_modal').modal('close'); 75 | $('#comment-form')[0].reset(); 76 | $('i#trans' + f[1].value).parent('td').html(f[2].value); 77 | } else if ('none' === q) { 78 | Materialize.toast('Error while saving comment') 79 | } 80 | } 81 | }); 82 | return false; 83 | }); 84 | $('a.scrollto').on('click', function () { 85 | var name = $(this).attr('href').slice(1); 86 | $('.collapsible').collapsible('open', $('a[name="' + name + '"]').parent('li').index() - 3); 87 | }); 88 | $('.tooltipped').tooltip({ 89 | delay: 50, 90 | html: true 91 | }); 92 | }); 93 | 94 | function getCookie(name) { 95 | var cookieValue = null; 96 | if (document.cookie && document.cookie !== '') { 97 | var cookies = document.cookie.split(';'); 98 | for (var i = 0; i < cookies.length; i++) { 99 | var cookie = jQuery.trim(cookies[i]); 100 | if (cookie.substring(0, name.length + 1) === (name + '=')) { 101 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); 102 | break; 103 | } 104 | } 105 | } 106 | return cookieValue; 107 | } 108 | 109 | var grid = document.getElementById('grid'); 110 | 111 | grid.onclick = function (e) { 112 | if (e.target.tagName != 'TH') return; 113 | sortGrid(e.target.cellIndex, e.target.getAttribute('data-type')); 114 | }; 115 | 116 | function sortGrid(colNum, type) { 117 | var tbody = grid.getElementsByTagName('tbody')[0]; 118 | var rowsArray = [].slice.call(tbody.rows); 119 | var compare; 120 | switch (type) { 121 | case 'number': 122 | compare = function (rowA, rowB) { 123 | return rowA.cells[colNum].innerHTML - rowB.cells[colNum].innerHTML; 124 | }; 125 | break; 126 | case 'string': 127 | compare = function (rowA, rowB) { 128 | return rowA.cells[colNum].innerHTML > rowB.cells[colNum].innerHTML ? 1 : -1; 129 | }; 130 | break; 131 | } 132 | rowsArray.sort(compare); 133 | grid.removeChild(tbody); 134 | for (var i = 0; i < rowsArray.length; i++) { 135 | tbody.appendChild(rowsArray[i]); 136 | } 137 | grid.appendChild(tbody); 138 | } 139 | 140 | Storage.prototype.setObject = function (key, value) { 141 | this.setItem(key, JSON.stringify(value)); 142 | }; 143 | 144 | Storage.prototype.getObject = function (key) { 145 | var value = this.getItem(key); 146 | try { 147 | return JSON.parse(value); 148 | } 149 | catch(err) { 150 | console.log("JSON parse failed for lookup of ", key, "\n error was: ", err); 151 | return null; 152 | } 153 | }; 154 | 155 | 156 | // function initHashChanges() { 157 | // var h = window.location.hash; 158 | // var pair = h.toUpperCase(); 159 | // pair = pair.substr(1, pair.length); // trim # 160 | // 161 | // // trace('on load hash is [' + h + ']'); 162 | // // set this so we know not to override it with localStorage or default currencyPair 163 | // if (currencyPairArray.indexOf(pair) != -1) { 164 | // hasHashCurrencyPair = true; 165 | // } 166 | // 167 | // evaluateHash(h); 168 | // 169 | // window.onhashchange = function() { 170 | // // trace("hash changed: " + window.location.hash); 171 | // clearTimeout(hashTimer); 172 | // evaluateHash(window.location.hash); 173 | // }; 174 | // } -------------------------------------------------------------------------------- /trade/static/trade/404.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/static/trade/404.jpg -------------------------------------------------------------------------------- /trade/templates/account/account_inactive.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Account Inactive" %}{% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |

{% trans "Account Inactive" %}

11 | 12 |

{% trans "This account is inactive." %}

13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /trade/templates/account/base.html: -------------------------------------------------------------------------------- 1 | {% extends 'trade/base.html' %} -------------------------------------------------------------------------------- /trade/templates/account/email.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Account" %}{% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |

{% trans "E-mail Addresses" %}

11 | {% if user.emailaddress_set.all %} 12 |

{% trans 'The following e-mail addresses are associated with your account:' %}

13 | 14 | 43 | 44 | {% else %} 45 |

{% trans 'Warning:'%} {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}

46 | 47 | {% endif %} 48 | 49 | 50 |

{% trans "Add E-mail Address" %}

51 | 52 |
53 | {% csrf_token %} 54 | {{ form.as_p }} 55 | 56 |
57 |
58 |
59 | {% endblock %} 60 | 61 | 62 | {% block extra_body %} 63 | 76 | {% endblock %} 77 | -------------------------------------------------------------------------------- /trade/templates/account/email/email_confirmation_message.txt: -------------------------------------------------------------------------------- 1 | {% load account %}{% user_display user as user_display %}{% load i18n %}{% autoescape off %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Hello from {{ site_name }}! 2 | 3 | You're receiving this e-mail because user {{ user_display }} has given yours as an e-mail address to connect their account. 4 | 5 | To confirm this is correct, go to {{ activate_url }} 6 | {% endblocktrans %}{% endautoescape %} 7 | {% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Thank you from {{ site_name }}! 8 | {{ site_domain }}{% endblocktrans %} 9 | -------------------------------------------------------------------------------- /trade/templates/account/email/email_confirmation_signup_message.txt: -------------------------------------------------------------------------------- 1 | {% include "account/email/email_confirmation_message.txt" %} 2 | -------------------------------------------------------------------------------- /trade/templates/account/email/email_confirmation_signup_subject.txt: -------------------------------------------------------------------------------- 1 | {% include "account/email/email_confirmation_subject.txt" %} 2 | -------------------------------------------------------------------------------- /trade/templates/account/email/email_confirmation_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% autoescape off %} 3 | {% blocktrans %}Please Confirm Your E-mail Address{% endblocktrans %} 4 | {% endautoescape %} 5 | -------------------------------------------------------------------------------- /trade/templates/account/email/password_reset_key_message.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Hello from {{ site_name }}! 2 | 3 | You're receiving this e-mail because you or someone else has requested a password for your user account. 4 | It can be safely ignored if you did not request a password reset. Click the link below to reset your password.{% endblocktrans %} 5 | 6 | {{ password_reset_url }} 7 | 8 | {% if username %}{% blocktrans %}In case you forgot, your username is {{ username }}.{% endblocktrans %} 9 | 10 | {% endif %}{% blocktrans with site_name=current_site.name site_domain=current_site.domain %}Thank you for using {{ site_name }}! 11 | {{ site_domain }}{% endblocktrans %} 12 | -------------------------------------------------------------------------------- /trade/templates/account/email/password_reset_key_subject.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% autoescape off %} 3 | {% blocktrans %}Password Reset E-mail{% endblocktrans %} 4 | {% endautoescape %} -------------------------------------------------------------------------------- /trade/templates/account/email_confirm.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load account %} 5 | 6 | {% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %} 7 | 8 | 9 | {% block content %} 10 |

{% trans "Confirm E-mail Address" %}

11 | 12 | {% if confirmation %} 13 | 14 | {% user_display confirmation.email_address.user as user_display %} 15 | 16 |

{% blocktrans with confirmation.email_address.email as email %}Please confirm that {{ email }} is an e-mail address for user {{ user_display }}.{% endblocktrans %}

17 | 18 |
19 | {% csrf_token %} 20 | 21 |
22 | 23 | {% else %} 24 | 25 | {% url 'account_email' as email_url %} 26 | 27 |

{% blocktrans %}This e-mail confirmation link expired or is invalid. Please issue a new e-mail confirmation request.{% endblocktrans %}

28 | 29 | {% endif %} 30 | 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /trade/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | {% load i18n %} 3 | {% load account socialaccount %} 4 | {% block head_title %}{% trans "Sign In" %}{% endblock %} 5 | {% block content %} 6 |
7 |
8 |

{% trans "Sign In" %}

9 | {% get_providers as socialaccount_providers %} 10 | {% if socialaccount_providers %} 11 |

{% blocktrans with site.name as site_name %}Please sign in with one 12 | of your existing third party accounts. Or, sign up 13 | for a {{ site_name }} account and sign in below:{% endblocktrans %}

14 |
15 |
    16 | {% include "socialaccount/snippets/provider_list.html" with process="login" %} 17 |
18 | 19 |
20 | {% include "socialaccount/snippets/login_extra.html" %} 21 | {% endif %} 22 | 23 | 57 |
58 |
59 | {% endblock %} 60 | -------------------------------------------------------------------------------- /trade/templates/account/logout.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Sign Out" %}{% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |

{% trans "Sign Out" %}

11 | 12 |

{% trans 'Are you sure you want to sign out?' %}

13 | 14 |
15 | {% csrf_token %} 16 | {% if redirect_field_value %} 17 | 18 | {% endif %} 19 | 20 |
21 |
22 |
23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /trade/templates/account/messages/cannot_delete_primary_email.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You cannot remove your primary e-mail address ({{email}}).{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/account/messages/email_confirmation_sent.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Confirmation e-mail sent to {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/account/messages/email_confirmed.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You have confirmed {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/account/messages/email_deleted.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Removed e-mail address {{email}}.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/account/messages/logged_in.txt: -------------------------------------------------------------------------------- 1 | {% load account %} 2 | {% load i18n %} 3 | {% user_display user as name %} 4 | {% blocktrans %}Successfully signed in as {{name}}.{% endblocktrans %} 5 | -------------------------------------------------------------------------------- /trade/templates/account/messages/logged_out.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}You have signed out.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/account/messages/password_changed.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Password successfully changed.{% endblocktrans %} 3 | 4 | -------------------------------------------------------------------------------- /trade/templates/account/messages/password_set.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Password successfully set.{% endblocktrans %} 3 | 4 | -------------------------------------------------------------------------------- /trade/templates/account/messages/primary_email_set.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Primary e-mail address set.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/account/messages/unverified_primary_email.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}Your primary e-mail address must be verified.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/account/password_change.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |

{% trans "Change Password" %}

11 | 12 |
13 | {% csrf_token %} 14 | {% if form.errors %} 15 | {% for field in form %} 16 | {% for error in field.errors %} 17 |
18 | {{ error|escape }} 19 |
20 | {% endfor %} 21 | {% endfor %} 22 | {% for error in form.non_field_errors %} 23 |
24 | {{ error|escape }} 25 |
26 | {% endfor %} 27 | {% endif %} 28 | {% for field in form %} 29 |
30 | {{ field }} 31 |
32 | {% endfor %} 33 | 35 |
36 |
37 |
38 | {% endblock %} -------------------------------------------------------------------------------- /trade/templates/account/password_reset.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load account %} 5 | 6 | {% block head_title %}{% trans "Password Reset" %}{% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |

{% trans "Password Reset" %}

12 | {% if user.is_authenticated %} 13 | {% include "account/snippets/already_logged_in.html" %} 14 | {% endif %} 15 | 16 |

{% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}

17 | 18 |
19 | {% csrf_token %} 20 |
21 | 22 | 23 |
24 | 25 |
26 | 27 |

{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}

28 |
29 |
30 | {% endblock %} 31 | -------------------------------------------------------------------------------- /trade/templates/account/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% load account %} 5 | 6 | {% block head_title %}{% trans "Password Reset" %}{% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |

{% trans "Password Reset" %}

12 | 13 | {% if user.is_authenticated %} 14 | {% include "account/snippets/already_logged_in.html" %} 15 | {% endif %} 16 | 17 |

{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

18 |
19 |
20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /trade/templates/account/password_reset_from_key.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 |

{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}

10 | 11 | {% if token_fail %} 12 | {% url 'account_reset_password' as passwd_reset_url %} 13 |

{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a new password reset.{% endblocktrans %}

14 | {% else %} 15 | {% if form %} 16 |
17 | {% csrf_token %} 18 | {% if form.errors %} 19 | {% for field in form %} 20 | {% for error in field.errors %} 21 |
22 | {{ error|escape }} 23 |
24 | {% endfor %} 25 | {% endfor %} 26 | {% for error in form.non_field_errors %} 27 |
28 | {{ error|escape }} 29 |
30 | {% endfor %} 31 | {% endif %} 32 |
33 | 34 | 35 |
36 |
37 | 38 | 39 |
40 | 41 |
42 | {% else %} 43 |

{% trans 'Your password is now changed.' %}

44 | {% endif %} 45 | {% endif %}
46 | {% endblock %} 47 | -------------------------------------------------------------------------------- /trade/templates/account/password_reset_from_key_done.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | {% block head_title %}{% trans "Change Password" %}{% endblock %} 5 | 6 | {% block content %} 7 |
8 |
9 |

{% trans "Change Password" %}

10 |

{% trans 'Your password is now changed.' %}

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /trade/templates/account/password_set.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Set Password" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Set Password" %}

9 | 10 |
11 | {% csrf_token %} 12 | {{ form.as_p }} 13 | 14 |
15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /trade/templates/account/signup.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Signup" %}{% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |

{% trans "Sign Up" %}

11 | 12 |

{% blocktrans %}Already have an account? Then please sign in.{% endblocktrans %}

13 | 14 | 40 |
41 |
42 | {% endblock %} 43 | -------------------------------------------------------------------------------- /trade/templates/account/signup_closed.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Sign Up Closed" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Sign Up Closed" %}

9 | 10 |

{% trans "We are sorry, but the sign up is currently closed." %}

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /trade/templates/account/snippets/already_logged_in.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% load account %} 3 | 4 | {% user_display user as user_display %} 5 |

{% trans "Note" %}: {% blocktrans %}you are already logged in as {{ user_display }}.{% endblocktrans %}

6 | -------------------------------------------------------------------------------- /trade/templates/account/verification_sent.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |

{% trans "Verify Your E-mail Address" %}

11 | 12 |

{% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}

13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /trade/templates/account/verified_email_required.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Verify Your E-mail Address" %}

9 | 10 | {% url 'account_email' as email_url %} 11 | 12 |

{% blocktrans %}This part of the site requires us to verify that 13 | you are who you claim to be. For this purpose, we require that you 14 | verify ownership of your e-mail address. {% endblocktrans %}

15 | 16 |

{% blocktrans %}We have sent an e-mail to you for 17 | verification. Please click on the link inside this e-mail. Please 18 | contact us if you do not receive it within a few minutes.{% endblocktrans %}

19 | 20 |

{% blocktrans %}Note: you can still change your e-mail address.{% endblocktrans %}

21 | 22 | 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /trade/templates/openid/base.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | -------------------------------------------------------------------------------- /trade/templates/openid/login.html: -------------------------------------------------------------------------------- 1 | {% extends "openid/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}OpenID Sign In{% endblock %} 6 | 7 | {% block content %} 8 | 9 |

{% trans 'OpenID Sign In' %}

10 | 11 | 12 | 17 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/authentication_error.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Social Network Login Failure" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Social Network Login Failure" %}

9 | 10 |

{% trans "An error occurred while attempting to login via your social network account." %}

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/base.html: -------------------------------------------------------------------------------- 1 | {% extends "account/base.html" %} 2 | 3 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/connections.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Account Connections" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Account Connections" %}

9 | 10 | {% if form.accounts %} 11 |

{% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}

12 | 13 | 14 |
15 | {% csrf_token %} 16 | 17 |
18 | {% if form.non_field_errors %} 19 |
{{ form.non_field_errors }}
20 | {% endif %} 21 | 22 | {% for base_account in form.accounts %} 23 | {% with base_account.get_provider_account as account %} 24 |
25 | 30 |
31 | {% endwith %} 32 | {% endfor %} 33 | 34 |
35 | 36 |
37 | 38 |
39 | 40 |
41 | 42 | {% else %} 43 |

{% trans 'You currently have no social network accounts connected to this account.' %}

44 | {% endif %} 45 | 46 |

{% trans 'Add a 3rd Party Account' %}

47 | 48 |
    49 | {% include "socialaccount/snippets/provider_list.html" with process="connect" %} 50 |
51 | 52 | {% include "socialaccount/snippets/login_extra.html" %} 53 | 54 | {% endblock %} 55 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/login_cancelled.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Login Cancelled" %}{% endblock %} 6 | 7 | {% block content %} 8 | 9 |

{% trans "Login Cancelled" %}

10 | 11 | {% url 'account_login' as login_url %} 12 | 13 |

{% blocktrans %}You decided to cancel logging in to our site using one of your existing accounts. If this was a mistake, please proceed to sign in.{% endblocktrans %}

14 | 15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/messages/account_connected.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account has been connected.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/messages/account_connected_other.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account is already connected to a different account.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/messages/account_disconnected.txt: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | {% blocktrans %}The social account has been disconnected.{% endblocktrans %} 3 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/signup.html: -------------------------------------------------------------------------------- 1 | {% extends "socialaccount/base.html" %} 2 | 3 | {% load i18n %} 4 | 5 | {% block head_title %}{% trans "Signup" %}{% endblock %} 6 | 7 | {% block content %} 8 |

{% trans "Sign Up" %}

9 | 10 |

{% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are about to use your {{provider_name}} account to login to 11 | {{site_name}}. As a final step, please complete the following form:{% endblocktrans %}

12 | 13 | 21 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/snippets/login_extra.html: -------------------------------------------------------------------------------- 1 | {% load socialaccount %} 2 | 3 | {% providers_media_js %} 4 | 5 | -------------------------------------------------------------------------------- /trade/templates/socialaccount/snippets/provider_list.html: -------------------------------------------------------------------------------- 1 | {% load socialaccount %} 2 | 3 | {% get_providers as socialaccount_providers %} 4 | 5 | {% for provider in socialaccount_providers %} 6 | {% if provider.id == "openid" %} 7 | {% for brand in provider.get_brands %} 8 |
  • 9 | {{brand.name}} 13 |
  • 14 | {% endfor %} 15 | {% endif %} 16 |
  • 17 | {{provider.name}} 19 |
  • 20 | {% endfor %} 21 | 22 | -------------------------------------------------------------------------------- /trade/templates/trade/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | TradeOnGrid 8 | 9 | 10 | 11 | 12 | 13 | {% block style %}{% endblock %} 14 | 15 | 16 | 28 | {% block content %}{% endblock %} 29 | 30 | 31 | 32 | {% block script %}{% endblock %} 33 | 34 | -------------------------------------------------------------------------------- /trade/templates/trade/coins.html: -------------------------------------------------------------------------------- 1 | {% load coin_full_name humanize %} 2 | {% if coins %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% for coin in coins %} 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {% endfor %} 29 | 30 |
    CoinNameAvailableOn tradeTotalBtc value (~)Last update
    {{ coin.coin }}{{ coin.coin | get_full_name }}{{ coin.free }}{{ coin.used }}{{ coin.total }}{{ coin.btc_value }}{{ coin.last_update | naturaltime }}
    31 | {% else %} 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
    NameAvailableLast update
    Coins not ready yet
    47 | {% endif %} 48 | -------------------------------------------------------------------------------- /trade/templates/trade/transactions.html: -------------------------------------------------------------------------------- 1 | {% load value_to_cryptotoken %} 2 | {% if transactions %} 3 | {% if item.wallet.name != 'Yandex Money' %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% for transaction in transactions %} 18 | 19 | 20 | 22 | 24 | 25 | 32 | 33 | 34 | 35 | {% endfor %} 36 | 37 |
    Block NumberFromToDateTypeValueHash
    {{ transaction.number }}{% if transaction.t_from == item.address %}This Wallet{% else %} 21 | {{ transaction.t_from | safe }}{% endif %}{% if transaction.t_to == item.address %}This Wallet{% else %} 23 | {{ transaction.t_to | safe }}{% endif %}{{ transaction.date }} 26 | {% if transaction.type == 'in' %} 27 | {{ transaction.type }} 28 | {% elif transaction.type == 'out' %} 29 | {{ transaction.type }} 30 | {% endif %} 31 | {{ transaction.value | value_to_cryptotoken:item }}{{ transaction.hash }}
    38 | {% else %} 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {% for transaction in transactions %} 53 | 54 | 55 | 56 | 63 | 64 | 65 | 66 | 67 | 68 | {% endfor %} 69 | 70 |
    Operation IDDateTypeAmountDetailsTitleComment
    {{ transaction.number }}{{ transaction.date }} 57 | {% if transaction.type == 'in' %} 58 | {{ transaction.type }} 59 | {% elif transaction.type == 'out' %} 60 | {{ transaction.type }} 61 | {% endif %} 62 | {{ transaction.value | value_to_cryptotoken:item }}{{ transaction.details }}{{ transaction.title }}{{ transaction.comment }}
    71 | {% endif %} 72 | {% else %} 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
    Block NumberFromToDateTypeValueBlockHashHash
    История транзакций отсутствует
    92 | {% endif %} 93 | -------------------------------------------------------------------------------- /trade/templates/trade/user_summaries.html: -------------------------------------------------------------------------------- 1 |
    Total balance {{ btc | floatformat:"-8"}} BTC / {{ usd | floatformat:"-2" }} USD ({% now "DATETIME_FORMAT" %})
    -------------------------------------------------------------------------------- /trade/templates/trade/wallet_info.html: -------------------------------------------------------------------------------- 1 | {% load value_to_cryptotoken %} 2 | {% if success == 1 %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
    Trans total:{{ total_trans }} РС
    In trans total:{{ in_trans | length }} РС
    Out trans total:{{ out_trans | length }} РС
    In trans total value:{{ in_trans_sum | value_to_cryptotoken:uw }}
    Out trans total value:{{ out_trans_sum | value_to_cryptotoken:uw }}
    25 | {% else %} 26 | Информация по данному кошельку отсутствует. 27 | {% endif %} 28 | -------------------------------------------------------------------------------- /trade/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/trade/templatetags/__init__.py -------------------------------------------------------------------------------- /trade/templatetags/coin_full_name.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.template.defaultfilters import stringfilter 3 | from trade.models import Coin 4 | 5 | register = template.Library() 6 | 7 | 8 | @register.filter(name='get_full_name') 9 | @stringfilter 10 | def get_full_name(short_name): 11 | try: 12 | coin = Coin.objects.get(short_name=short_name.upper()) 13 | return str(coin.full_name) 14 | except Coin.DoesNotExist: 15 | return '-' 16 | -------------------------------------------------------------------------------- /trade/templatetags/coins.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from trade.models import UserBalance 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.inclusion_tag('trade/coins.html') 8 | def get_coins(ue): 9 | coins = UserBalance.objects.filter(ue=ue).order_by('-total') 10 | return {'coins': coins} 11 | -------------------------------------------------------------------------------- /trade/templatetags/summary_balance.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from trade.models import UserWallet, UserExchange 3 | import requests 4 | 5 | register = template.Library() 6 | 7 | 8 | @register.filter 9 | def get_user_summaries_btc(user): 10 | btc_total = float(0) 11 | usd_total = float(0) 12 | wallets = UserWallet.objects.all() 13 | exchanges = UserExchange.objects.all() 14 | if wallets is not None: 15 | for wallet in wallets: 16 | usd_total += float(wallet.total_usd) 17 | if exchanges is not None: 18 | for exchange in exchanges: 19 | usd_total += float(exchange.total_usd) 20 | if usd_total > 0: 21 | btc_price = requests.get('https://api.cryptonator.com/api/full/btc-usd').json() 22 | btc_total = usd_total / float(btc_price['ticker']['price']) 23 | return btc_total 24 | 25 | 26 | @register.filter 27 | def get_user_summaries_usd(user): 28 | usd_total = float(0) 29 | wallets = UserWallet.objects.all() 30 | exchanges = UserExchange.objects.all() 31 | if wallets is not None: 32 | for wallet in wallets: 33 | usd_total += float(wallet.total_usd) 34 | if exchanges is not None: 35 | for exchange in exchanges: 36 | usd_total += float(exchange.total_usd) 37 | return usd_total 38 | 39 | 40 | @register.filter 41 | def as_percent_of(part, whole): 42 | try: 43 | return float(part) / whole * 100 44 | except (ValueError, ZeroDivisionError): 45 | return 0 46 | -------------------------------------------------------------------------------- /trade/templatetags/transactions.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from trade.models import Transaction 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.inclusion_tag('trade/transactions.html') 8 | def get_transactions(uw): 9 | transactions = Transaction.objects.all().order_by('-date') 10 | return {'transactions': transactions, 'item': uw} 11 | -------------------------------------------------------------------------------- /trade/templatetags/value_to_cryptotoken.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from trade.models import Transaction, UserWallet 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.filter(name='value_to_cryptotoken') 8 | def value_to_cryptotoken(value, item): 9 | if type(item) == UserWallet: 10 | if item.wallet.name == 'ETH': 11 | return str(round(float(value / (10 ** 18)), 8)) + ' ETH' 12 | elif item.wallet.name == 'BTC': 13 | return str(round(float(value), 8)) + ' BTC' 14 | elif item.wallet.name == 'Yandex Money': 15 | return str(round(float(value), 2)) + ' RUR' 16 | elif type(item) == Transaction: 17 | if item.name[0] == 'E': 18 | return str(round(float(value / (10 ** 18)), 8)) + ' ETH' 19 | elif item.name[0] == 'B': 20 | return str(round(float(value), 8)) + ' BTC' 21 | elif item.name[0] == 'Y': 22 | return str(round(float(value), 2)) + ' RUR' 23 | else: 24 | return str(round(float(value), 2)) + ' ' + item.currency 25 | -------------------------------------------------------------------------------- /trade/templatetags/wallet_information.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from trade.models import Transaction 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.inclusion_tag('trade/wallet_info.html') 8 | def get_wallet_info(uw): 9 | transactions = Transaction.objects.filter(name=uw.wallet.name + str(uw.pk)).order_by('-date') 10 | if len(transactions) > 0: 11 | in_trans = list(transactions.filter(type='in')) 12 | out_trans = transactions.filter(type='out') 13 | in_trans_sum = 0 14 | out_trans_sum = 0 15 | for item in in_trans: 16 | in_trans_sum += item.value 17 | for item in out_trans: 18 | out_trans_sum += item.value 19 | return {'uw': uw, 20 | 'success': 1, 21 | 'total_trans': len(transactions), 22 | 'in_trans': in_trans, 23 | 'out_trans': out_trans, 24 | 'in_trans_sum': in_trans_sum, 25 | 'out_trans_sum': out_trans_sum 26 | } 27 | else: 28 | return {'success': 0} 29 | -------------------------------------------------------------------------------- /trade/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /trade/views.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import requests 4 | import re 5 | import djangoTrade.settings as settings 6 | from django.core import serializers 7 | from django.core.exceptions import ObjectDoesNotExist 8 | from django.http import HttpResponse 9 | from django.shortcuts import render, redirect 10 | from django.contrib.auth.decorators import login_required 11 | from trade.forms import UserExchangesForm, UserWalletForm 12 | from trade.models import UserExchange, Exchanges, UserBalance, UserWallet, Wallets, Transaction, UserHoldings 13 | from yandex_money.api import Wallet, ExternalPayment 14 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 15 | from django.core.serializers.json import DjangoJSONEncoder 16 | 17 | 18 | @login_required 19 | def index(request): 20 | transaction = Transaction.objects.all().order_by('-date') 21 | if len(transaction) > 0: 22 | paginator = Paginator(transaction, 100) 23 | page = request.GET.get('page') 24 | try: 25 | transactions = paginator.page(page) 26 | except PageNotAnInteger: 27 | transactions = paginator.page(1) 28 | except EmptyPage: 29 | transactions = paginator.page(paginator.num_pages) 30 | else: 31 | transactions = None 32 | args = {'exchange_form': UserExchangesForm(), 33 | 'wallet_form': UserWalletForm(), 34 | 'ue': UserExchange.objects.all(), 35 | 'uw': UserWallet.objects.all(), 36 | 'trans': transactions} 37 | return render(request, 'trade/home.html', args) 38 | 39 | 40 | def change_status(request): 41 | try: 42 | ue = UserExchange.objects.get(pk=request.POST['ue']) 43 | except ObjectDoesNotExist: 44 | return HttpResponse('none', status=200) 45 | ue.is_active = not ue.is_active 46 | ue.save() 47 | return HttpResponse('ok', status=200) 48 | 49 | 50 | @login_required 51 | def exchange(request): 52 | if request.method == 'POST': 53 | ue = UserExchange() 54 | ue.user = request.user 55 | ue.exchange = Exchanges.objects.get(pk=request.POST.get('exchange')) 56 | ue.apikey = request.POST.get('apikey') 57 | ue.apisecret = request.POST.get('apisecret') 58 | ue.total_btc = float(0) 59 | ue.save() 60 | return redirect(index) 61 | 62 | 63 | @login_required 64 | def wallet(request): 65 | if request.method == 'POST': 66 | wallet = Wallets.objects.get(pk=request.POST.get('wallet')) 67 | if wallet.name == 'Yandex Money': 68 | if not settings.YANDEX_MONEY_CLIENT_ID or not settings.YANDEX_MONEY_REDIRECT_URI or not \ 69 | settings.YANDEX_MONEY_CLIENT_SECRET: 70 | return HttpResponse('You must define yandex money settings', status=404) 71 | scope = ['account-info', 'operation-history', 'operation-details'] 72 | auth_url = Wallet.build_obtain_token_url( 73 | client_id=settings.YANDEX_MONEY_CLIENT_ID, 74 | redirect_uri=settings.YANDEX_MONEY_REDIRECT_URI, 75 | scope=scope) + '&response_type=code' 76 | return redirect(auth_url) 77 | else: 78 | uw = UserWallet() 79 | uw.user = request.user 80 | uw.address = request.POST.get('address') 81 | uw.wallet = wallet 82 | uw.save() 83 | elif request.method == 'GET': 84 | if not settings.YANDEX_MONEY_CLIENT_ID or not settings.YANDEX_MONEY_REDIRECT_URI or not \ 85 | settings.YANDEX_MONEY_CLIENT_SECRET: 86 | return HttpResponse('You must define yandex money settings', status=404) 87 | access_token = Wallet.get_access_token( 88 | client_id=settings.YANDEX_MONEY_CLIENT_ID, 89 | redirect_uri=settings.YANDEX_MONEY_REDIRECT_URI, 90 | code=request.GET.get('code'), 91 | client_secret=settings.YANDEX_MONEY_CLIENT_SECRET 92 | ) 93 | access_token = access_token['access_token'] 94 | wallet = Wallet(access_token) 95 | account_info = wallet.account_info() 96 | uw = UserWallet() 97 | uw.wallet = Wallets.objects.get(name='Yandex Money') 98 | uw.access_token = access_token 99 | uw.user = request.user 100 | uw.address = account_info['account'] 101 | uw.balance = account_info['balance'] 102 | uw.save() 103 | return redirect(index) 104 | 105 | 106 | @login_required 107 | def get_holding(request): 108 | type_r = request.GET.get('type') 109 | if request.is_ajax(): 110 | if type_r == 'names': 111 | names = [] 112 | user_hold_names = UserHoldings.objects.values('type').distinct() 113 | if len(user_hold_names) > 0: 114 | for name in user_hold_names: 115 | names.append(name['type']) 116 | return HttpResponse(json.dumps(names), status=200) 117 | else: 118 | return HttpResponse('none', status=200) 119 | else: 120 | holdings = UserHoldings.objects.filter(type=type_r).order_by('date_time') 121 | list_hold = [obj.as_list() for obj in holdings] 122 | return HttpResponse(json.dumps(list_hold, cls=DjangoJSONEncoder), status=200) 123 | 124 | 125 | def add_new_transaction_comment(request): 126 | if request.POST: 127 | tr_id = request.POST.get('tr_id') 128 | comment = request.POST.get('comment') 129 | try: 130 | trans = Transaction.objects.get(pk=tr_id) 131 | trans.user_comment = comment 132 | trans.save() 133 | except Transaction.DoesNotExist: 134 | return HttpResponse('none', status=200) 135 | return HttpResponse('ok', status=200) 136 | -------------------------------------------------------------------------------- /tradeBOT/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/tradeBOT/__init__.py -------------------------------------------------------------------------------- /tradeBOT/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from tradeBOT import models 3 | 4 | 5 | class CalculationsAdmin(admin.ModelAdmin): 6 | list_display = ['user_pair', 'type', 'depth_coef', 'price', 'amount', 'date_created'] 7 | 8 | class Meta: 9 | model = models.Сalculations 10 | 11 | 12 | class UserOrderAdmin(admin.ModelAdmin): 13 | list_display = [field.name for field in models.UserOrder._meta.fields] 14 | list_filter = ['ue__exchange__name', 'order_type', 'ue__user__username'] 15 | 16 | class Meta: 17 | model = models.UserOrder 18 | 19 | 20 | class UserPairInline(admin.TabularInline): 21 | model = models.UserPair 22 | 23 | 24 | class ExchangeCoinAdmin(admin.ModelAdmin): 25 | search_fields = ['symbol', 'name'] 26 | list_filter = ['exchange'] 27 | 28 | class Meta: 29 | model = models.ExchangeCoin 30 | 31 | 32 | class UserPairAdmin(admin.ModelAdmin): 33 | list_display = [field.name for field in models.UserPair._meta.fields] 34 | list_filter = ['user', 'pair__main_coin__exchange__name'] 35 | 36 | class Meta: 37 | model = models.UserPair 38 | 39 | 40 | class CoinMarketCupCoinAdmin(admin.ModelAdmin): 41 | search_fields = ['name', 'symbol'] 42 | 43 | def get_ordering(self, request): 44 | return ['rank'] 45 | 46 | class Meta: 47 | model = models.CoinMarketCupCoin 48 | 49 | 50 | class PairAdmin(admin.ModelAdmin): 51 | search_fields = ['main_coin', 'second_coin'] 52 | list_filter = ['main_coin__exchange__name'] 53 | inlines = [UserPairInline] 54 | 55 | 56 | # class ExchangeTickerAdmin(admin.ModelAdmin): 57 | # list_display = [field.name for field in models.ExchangeTicker._meta.fields] 58 | # list_filter = ['exchange', 'pair'] 59 | # 60 | # class Meta: 61 | # model = models.ExchangeTicker 62 | 63 | 64 | class OrderAdmin(admin.ModelAdmin): 65 | list_display = [field.name for field in models.Order._meta.fields] 66 | list_filter = ['pair', 'ue'] 67 | search_fields = ['orderNumber'] 68 | 69 | class Meta: 70 | model = models.Order 71 | 72 | 73 | class ToTradeAdmin(admin.ModelAdmin): 74 | list_display = [field.name for field in models.ToTrade._meta.fields] 75 | list_filter = ['user_pair__user_exchange', 'type', 'user_pair__pair'] 76 | 77 | class Meta: 78 | model = models.ToTrade 79 | 80 | 81 | class ExtremumAdmin(admin.ModelAdmin): 82 | list_display = [field.name for field in models.Extremum._meta.fields] 83 | 84 | class Meta: 85 | model = models.Extremum 86 | 87 | admin.site.register(models.ExchangeCoin, ExchangeCoinAdmin) 88 | admin.site.register(models.UserPair, UserPairAdmin) 89 | admin.site.register(models.Pair, PairAdmin) 90 | admin.site.register(models.ExchangeMainCoin) 91 | admin.site.register(models.CoinMarketCupCoin, CoinMarketCupCoinAdmin) 92 | admin.site.register(models.UserMainCoinPriority) 93 | # admin.site.register(models.ExchangeTicker, ExchangeTickerAdmin) 94 | admin.site.register(models.Order, OrderAdmin) 95 | admin.site.register(models.ToTrade, ToTradeAdmin) 96 | admin.site.register(models.UserOrder, UserOrderAdmin) 97 | admin.site.register(models.UserCoinShare) 98 | admin.site.register(models.Сalculations, CalculationsAdmin) 99 | admin.site.register(models.Extremum, ExtremumAdmin) 100 | -------------------------------------------------------------------------------- /tradeBOT/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class TradebotConfig(AppConfig): 5 | name = 'tradeBOT' 6 | -------------------------------------------------------------------------------- /tradeBOT/consumers.py: -------------------------------------------------------------------------------- 1 | from channels import Group 2 | 3 | 4 | def ws_add(message): 5 | message.reply_channel.send({"accept": True}) 6 | Group("trade").add(message.reply_channel) 7 | 8 | 9 | def ws_disconnect(message): 10 | Group("trade").discard(message.reply_channel) 11 | -------------------------------------------------------------------------------- /tradeBOT/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/tradeBOT/migrations/__init__.py -------------------------------------------------------------------------------- /tradeBOT/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import User 2 | from django.db import models 3 | from trade.models import Exchanges, UserExchange 4 | 5 | 6 | # Create your models here. 7 | class ExchangeCoin(models.Model): 8 | exchange = models.ForeignKey(Exchanges) 9 | symbol = models.CharField(max_length=10) 10 | rank = models.IntegerField(default=0) 11 | 12 | def __str__(self): 13 | return self.exchange.name + ' ' + self.symbol 14 | 15 | class Meta: 16 | verbose_name = "Монета биржи" 17 | verbose_name_plural = "Монеты биржи" 18 | 19 | 20 | class UserPair(models.Model): 21 | user = models.ForeignKey(User) 22 | user_exchange = models.ForeignKey(UserExchange) 23 | pair = models.ForeignKey('Pair') 24 | rank = models.PositiveIntegerField(default=1) 25 | rate_of_change = models.DecimalField(max_digits=20, decimal_places=8, default=0) 26 | 27 | class Meta: 28 | verbose_name = "Пара пользователя" 29 | verbose_name_plural = "Пары пользователей" 30 | 31 | def __str__(self): 32 | return str( 33 | self.user_exchange) + ': ' + self.pair.main_coin.symbol.upper() + '_' + self.pair.second_coin.symbol.upper() 34 | 35 | 36 | class UserCoinShare(models.Model): 37 | user_exchange = models.ForeignKey(UserExchange) 38 | coin = models.ForeignKey(ExchangeCoin) 39 | share = models.DecimalField(decimal_places=2, max_digits=5, default=0) 40 | 41 | def __str__(self): 42 | return self.user_exchange.exchange.name + ': ' + self.coin.symbol + ' ' + str(self.share) 43 | 44 | class Meta: 45 | verbose_name = 'Доля валюты' 46 | verbose_name_plural = 'Доли валют' 47 | 48 | 49 | class ExchangeMainCoin(models.Model): 50 | coin = models.ForeignKey(ExchangeCoin) 51 | 52 | def __str__(self): 53 | return self.coin.exchange.name + ': ' + self.coin.symbol 54 | 55 | class Meta: 56 | verbose_name = "Главная монета биржи" 57 | verbose_name_plural = "Главные монеты биржи" 58 | 59 | 60 | class Pair(models.Model): 61 | main_coin = models.ForeignKey(ExchangeCoin, related_name='%(class)s_main_coin') 62 | second_coin = models.ForeignKey(ExchangeCoin, related_name='%(class)s_second_coin') 63 | is_active = models.BooleanField(default=True) 64 | 65 | def __str__(self): 66 | return self.main_coin.exchange.name + ': ' + self.main_coin.symbol.upper() + '_' + \ 67 | self.second_coin.symbol.upper() 68 | 69 | class Meta: 70 | verbose_name = "Пара" 71 | verbose_name_plural = "Пары" 72 | 73 | 74 | class UserMainCoinPriority(models.Model): 75 | user_exchange = models.ForeignKey(UserExchange) 76 | main_coin = models.ForeignKey(ExchangeMainCoin) 77 | priority = models.PositiveIntegerField() 78 | is_active = models.BooleanField() 79 | 80 | def __str__(self): 81 | return '%s %s' % (self.user_exchange.exchange.name, self.main_coin) 82 | 83 | class Meta: 84 | verbose_name_plural = 'Главные монеты пользователей' 85 | verbose_name = 'Главная монета пользователя' 86 | 87 | 88 | class CoinMarketCupCoin(models.Model): 89 | coin_market_id = models.CharField(max_length=63, verbose_name="Внутренее имя", default='') 90 | name = models.CharField(max_length=63, verbose_name="Имя") 91 | symbol = models.CharField(max_length=15, verbose_name="Аббр") 92 | rank = models.PositiveIntegerField() 93 | price_usd = models.DecimalField(decimal_places=8, max_digits=30, verbose_name="Цена в USD") 94 | volume_usd_24h = models.DecimalField(decimal_places=8, max_digits=30, null=True) 95 | available_supply = models.DecimalField(decimal_places=8, max_digits=30, null=True) 96 | total_supply = models.DecimalField(decimal_places=8, max_digits=30, null=True) 97 | 98 | class Meta: 99 | verbose_name = 'Монета CoinMarketCup' 100 | verbose_name_plural = 'Монеты CoinMarketCup' 101 | 102 | def __str__(self): 103 | return self.name + ' ' + self.symbol 104 | 105 | 106 | class Order(models.Model): 107 | ue = models.ForeignKey(UserExchange) 108 | pair = models.CharField(max_length=50) 109 | globalTradeID = models.BigIntegerField() 110 | tradeID = models.BigIntegerField() 111 | orderNumber = models.BigIntegerField() 112 | category = models.CharField(max_length=50) 113 | type = models.CharField(max_length=10) 114 | amount = models.DecimalField(max_digits=20, decimal_places=8) 115 | rate = models.DecimalField(max_digits=20, decimal_places=8) 116 | fee = models.DecimalField(max_digits=10, decimal_places=8) 117 | total = models.DecimalField(max_digits=20, decimal_places=8) 118 | our_total = models.DecimalField(max_digits=20, decimal_places=8) 119 | is_ok = models.CharField(max_length=5) 120 | date_time = models.DateTimeField() 121 | 122 | 123 | class UserOrder(models.Model): 124 | ue = models.ForeignKey(UserExchange) 125 | pair = models.ForeignKey(Pair) 126 | order_type = models.CharField(max_length=5) 127 | order_number = models.BigIntegerField() 128 | main_coin_before_total = models.DecimalField(max_digits=20, decimal_places=10) 129 | main_coin_before_free = models.DecimalField(max_digits=20, decimal_places=10) 130 | main_coin_before_used = models.DecimalField(max_digits=20, decimal_places=10) 131 | second_coin_before_total = models.DecimalField(max_digits=20, decimal_places=10) 132 | second_coin_before_free = models.DecimalField(max_digits=20, decimal_places=10) 133 | second_coin_before_used = models.DecimalField(max_digits=20, decimal_places=10) 134 | main_coin_after_total = models.DecimalField(max_digits=20, decimal_places=10, default=None, blank=True, null=True) 135 | main_coin_after_free = models.DecimalField(max_digits=20, decimal_places=10, default=None, blank=True, null=True) 136 | main_coin_after_used = models.DecimalField(max_digits=20, decimal_places=10, default=None, blank=True, null=True) 137 | second_coin_after_total = models.DecimalField(max_digits=20, decimal_places=10, default=None, blank=True, null=True) 138 | second_coin_after_free = models.DecimalField(max_digits=20, decimal_places=10, default=None, blank=True, null=True) 139 | second_coin_after_used = models.DecimalField(max_digits=20, decimal_places=10, default=None, blank=True, null=True) 140 | price = models.DecimalField(max_digits=20, decimal_places=10) 141 | amount = models.DecimalField(max_digits=20, decimal_places=10) 142 | total = models.DecimalField(max_digits=20, decimal_places=10) 143 | fee = models.DecimalField(max_digits=8, decimal_places=5) 144 | fact_total = models.DecimalField(max_digits=20, decimal_places=10, default=None, blank=True, null=True) 145 | fact_fee = models.DecimalField(max_digits=7, decimal_places=5, default=None, blank=True, null=True) 146 | is_ok = models.NullBooleanField(default=None, blank=True, null=True) 147 | interim_main_coin = models.DecimalField(max_digits=20, decimal_places=10) 148 | date_created = models.DateTimeField(auto_now_add=True) 149 | date_cancel = models.DateTimeField(default=None, blank=True, null=True) 150 | cancel_desc = models.CharField(max_length=100, blank=True, null=True, default=None) 151 | date_updated = models.DateTimeField(auto_now=True) 152 | to_close = models.BooleanField(default=False) 153 | 154 | def __str__(self): 155 | return self.ue.user.username + ' ' + self.ue.exchange.name + ': ' + self.order_type + ' ' + self.pair.main_coin.symbol.upper() + '_' + self.pair.second_coin.symbol.upper() 156 | 157 | class Meta: 158 | verbose_name_plural = 'Ордера пользователей' 159 | verbose_name = 'Ордер пользователя' 160 | ordering = ('date_created',) 161 | 162 | 163 | class ToTrade(models.Model): 164 | user_pair = models.ForeignKey(UserPair, blank=False, null=False) 165 | type = models.CharField(max_length=10, blank=False, null=False) 166 | price = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False) 167 | amount = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False) 168 | total = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False) 169 | total_f = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False, default=0) 170 | fee = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False) 171 | cause = models.CharField(max_length=255) 172 | date_created = models.DateTimeField(auto_now_add=True) 173 | date_updated = models.DateTimeField(auto_now=True) 174 | 175 | def __str__(self): 176 | return str(self.user_pair.pair) + ' ' + self.type 177 | 178 | class Meta: 179 | verbose_name = 'Пара готовая к торговле' 180 | verbose_name_plural = 'Пары готовые к торговле' 181 | 182 | 183 | class Сalculations(models.Model): 184 | user_pair = models.ForeignKey(UserPair) 185 | type = models.CharField(max_length=10) 186 | depth_coef = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False) 187 | price = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False) 188 | amount = models.DecimalField(max_digits=16, decimal_places=8, blank=False, null=False) 189 | bids = models.TextField(blank=True, null=True) 190 | asks = models.TextField(blank=True, null=True) 191 | date_created = models.DateTimeField(auto_now=True) 192 | 193 | 194 | class Extremum(models.Model): 195 | pair = models.ForeignKey(Pair) 196 | ext_type = models.CharField(max_length=10) 197 | price = models.DecimalField(max_digits=20, decimal_places=10) 198 | date = models.DateTimeField(auto_now=True) 199 | 200 | class Meta: 201 | verbose_name = 'Экстремум' 202 | verbose_name_plural = 'Экстремумы' 203 | 204 | def __str__(self): 205 | return self.pair.main_coin.symbol.upper() + '_' + self.pair.second_coin.symbol.upper() + ' ' + self.ext_type + ': ' + str( 206 | self.date) 207 | -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/Coins.html: -------------------------------------------------------------------------------- 1 | {% if coins %} 2 |

    Exchange: {{ exch.exchange }}

    3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% for coin in coins %} 12 | 13 | 14 | 15 | 16 | {% endfor %} 17 | 18 |
    NameSymbol
    {{ coin.name }}{{ coin.symbol }}
    19 | {% endif %} -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/coin_info.html: -------------------------------------------------------------------------------- 1 |
      2 |
    1. 3 | Rank: {{ coin.rank }} 4 |
    2. 5 |
    3. 6 | Price usd: {{ coin.price_usd | floatformat:'-2'}} 7 |
    4. 8 |
    5. 9 | Volume usd 24h: {{ coin.volume_usd_24h | floatformat:'-2'}} 10 |
    6. 11 |
    7. 12 | Available supply: {{ coin.available_supply | floatformat:'-2'}} 13 |
    8. 14 |
    -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/exchange_primary_coins.html: -------------------------------------------------------------------------------- 1 | {% load relations %} 2 | {% for pc in primary_coins %} 3 |
    4 |
      5 |
    • 6 |
      {{ pc.coin.name }} ({{ pc.coin.symbol }}) 7 |
      8 |
      {% primary_coin_pairs pc %}
      9 |
    • 10 |
    11 |
    12 | {% empty %} 13 | Netu primary coins 14 | {% endfor %} -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/get_primary_pairs.html: -------------------------------------------------------------------------------- 1 | {% load tradeBot_filters get_coin_info %} 2 | {% if pairs %} 3 | 8 | {% for pair in pairs %} 9 |
  • 10 |
    11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | {% with pair|get_change_percent:user_exchange as percent %} 33 | 37 | {% endwith %} 38 | 39 | 40 | 50 | 51 | 52 | 53 |
    {{ pair.second_coin.symbol | upper }}{{ pair|get_last:user_exchange }} 26 | {% if pair|get_change_percent:user_exchange > 0 %} 27 | 28 | {% elif pair|get_change_percent:user_exchange < 0 %} 29 | 30 | {% endif %} 31 | 35 | {{ percent }}% 36 | {{ pair.second_coin.symbol | user_have_coin:user_exchange | floatformat:"-8" }}{{ pair.is_active | yesno:'a,f' }} 41 |
    42 | {% csrf_token %} 43 | 45 | 46 | 48 |
    49 |
    54 |
    55 |
    56 |
    59 |
    60 |
  • 61 | {% endfor %} 62 | {% endif %} -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'trade/base.html' %} 2 | {% block content %} 3 | 12 | 13 |

    Your trade coins

    14 | {% for coin in user_coins %} 15 | {{ coin }} 16 | {% endfor %} 17 | {% endblock %} -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/orders.html: -------------------------------------------------------------------------------- 1 | {% load tradeBot_filters %} 2 | {% if orders %} 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {% for item in orders %} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {% endfor %} 37 | 38 |
    PairTypeOrder numberPriceAmountTotalFeeFact totalFact feeStatusCreatedCanceled/Closed
    {{ item.pair.main_coin.symbol.upper }}_{{ item.pair.second_coin.symbol.upper }}{{ item.order_type }}{{ item.order_number }}{{ item.price }}{{ item.amount }}{{ item.total }}{{ item.fee }}{{ item.fact_total }}{{ item.fact_fee }}{% if item.cancel_desc %}{{ item.cancel_desc }}{% else %}Working{% endif %}{{ item.date_created | date:'d.m.Y H:i:s' }}{% if item.date_cancel %}{{ item.date_cancel | date:'d.m.Y H:i:s' }}{% else %}-{% endif %}
    39 | {% endif %} 40 | -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/pairs.html: -------------------------------------------------------------------------------- 1 | {% load tradeBot_filters %} 2 | Available pairs: 3 | {% for pair in pairs %} 4 | {{ pair.main_coin.symbol }}-{{ pair.second_coin.symbol }} 5 | {% empty %} 6 | None 7 | {% endfor %} -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/primary_coin_pairs.html: -------------------------------------------------------------------------------- 1 | {% load get_coin_info %} 2 | {% for pair in pairs %} 3 |
      4 |
    • 5 |
      {{ pair.main_coin.symbol }}-{{ pair.second_coin.symbol }} 6 |
      7 |
      8 |
      {{ pair.main_coin.name }} {{ pair.main_coin.symbol }}
      9 | {% coin_info pair.main_coin.symbol %} 10 |
      {{ pair.second_coin.name }} {{ pair.second_coin.symbol }}
      11 | {% coin_info pair.second_coin.symbol %} 12 |
      13 |
    • 14 |
    15 | {% empty %} 16 | Netu pairs 17 | {% endfor %} -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/relations.html: -------------------------------------------------------------------------------- 1 | {% extends 'trade/base.html' %} 2 | {% load relations %} 3 | {% block content %} 4 |
    5 | {% for exchange in exchanges %} 6 |
      7 |
    • 8 |
      {{ exchange.exchange }} 9 |
      10 |
      {% exchange_primary_coins exchange %}
      11 |
    • 12 |
    13 | {% endfor %} 14 |
    15 | {% endblock %} -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | Document 9 | 24 | 25 | 26 |
    27 |
    28 |
    29 |
    30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 |
    ghbdtngjrfadawdadwadadadadad 38 |
    wdadadawdadwawdadadawdawdadadawdadwawdadadawdawdadadawdadw awdadadawdawdadadawdadwawdadadawdawdadadawdadwawdadadawdadwawdadadaw dadwawdadadawdadwawdadadawdadwawdadadawdadwawdadadawdadw 39 |
    40 |
    44 |
    45 |
    46 |
    47 | 48 |
    49 |
    50 | 51 | 52 | -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/to_trade.html: -------------------------------------------------------------------------------- 1 | {% load tradeBot_filters %} 2 | {% if to_trade %} 3 |
    Calculated values
    4 | {% endif %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for item in to_trade %} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | {% endfor %} 37 | 38 |
    PairRateTypePriceAmountTotalTotal + feeFeeCauseDate createdDate updated
    {{ item.user_pair.pair.main_coin.symbol.upper }}_{{ item.user_pair.pair.second_coin.symbol.upper }}{{ item.percent_react | multiple:100 | floatformat:'2' }}{{ item.type }}{{ item.price }}{{ item.amount }}{{ item.total }}{{ item.total_f }}{{ item.fee }}{{ item.cause }}{{ item.date_created | date:'d.m.Y H:i:s' }}{{ item.date_updated | date:'d.m.Y H:i:s' }}
    39 | -------------------------------------------------------------------------------- /tradeBOT/templates/tradeBOT/user_primary.html: -------------------------------------------------------------------------------- 1 | {% if success %} 2 | Priority: {{ coin.priority }} 3 |
    5 |
    6 | 12 |
    13 | {% else %} 14 | Priority: 1 15 |
    17 |
    18 | 24 |
    25 | {% endif %} 26 |
    -------------------------------------------------------------------------------- /tradeBOT/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/tradeBOT/templatetags/__init__.py -------------------------------------------------------------------------------- /tradeBOT/templatetags/get_coin_info.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from tradeBOT.models import CoinMarketCupCoin 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.inclusion_tag('tradeBOT/coin_info.html') 8 | def coin_info(symbol): 9 | try: 10 | coin = CoinMarketCupCoin.objects.get(symbol=symbol) 11 | except CoinMarketCupCoin.DoesNotExist: 12 | return None 13 | except CoinMarketCupCoin.MultipleObjectsReturned: 14 | return None 15 | return {'coin': coin} 16 | -------------------------------------------------------------------------------- /tradeBOT/templatetags/get_exchange_coins.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | from trade.models import Exchanges 4 | from tradeBOT.models import ExchangeCoin 5 | 6 | register = template.Library() 7 | 8 | 9 | @register.inclusion_tag('tradeBOT/Coins.html') 10 | def exchange_coins(exch): 11 | exchange = Exchanges.objects.get(exchange=exch) 12 | exch_coins = ExchangeCoin.objects.filter(exchange=exchange).order_by('-is_active', 'name') 13 | return { 14 | 'exch': exchange, 15 | 'coins': exch_coins, 16 | } 17 | -------------------------------------------------------------------------------- /tradeBOT/templatetags/relations.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from tradeBOT.models import ExchangeMainCoin, Pair 3 | 4 | register = template.Library() 5 | 6 | 7 | @register.inclusion_tag('tradeBOT/exchange_primary_coins.html') 8 | def exchange_primary_coins(exchange): 9 | try: 10 | primary_coins = ExchangeMainCoin.objects.filter(coin__exchange=exchange) 11 | return {'primary_coins': primary_coins} 12 | except ExchangeMainCoin.DoesNotExist: 13 | return None 14 | 15 | 16 | @register.inclusion_tag('tradeBOT/primary_coin_pairs.html') 17 | def primary_coin_pairs(primary_coin): 18 | try: 19 | pairs = Pair.objects.filter(main_coin=primary_coin.coin) 20 | return {'pairs': pairs} 21 | except Pair.DoesNotExist: 22 | return None 23 | -------------------------------------------------------------------------------- /tradeBOT/templatetags/tradeBot_filters.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | from ticker_app.models import ExchangeTicker 4 | from tradeBOT.models import CoinMarketCupCoin, UserMainCoinPriority, Pair, ExchangeMainCoin, UserPair 5 | from trade.models import UserBalance 6 | 7 | register = template.Library() 8 | 9 | 10 | @register.filter(name='user_have_coin') 11 | def user_holdings(coin_symbol, user_exchange): 12 | try: 13 | user_hold = UserBalance.objects.get(ue_id=user_exchange, coin=coin_symbol) 14 | return user_hold.total 15 | except UserBalance.DoesNotExist: 16 | return 0 17 | 18 | 19 | @register.filter(name='get_coinmarket_id') 20 | def get_coinmarket_id(symbol): 21 | try: 22 | coin_market_id = CoinMarketCupCoin.objects.filter(symbol=symbol).earliest('rank') 23 | return coin_market_id.coin_market_id 24 | except CoinMarketCupCoin.DoesNotExist: 25 | return '' 26 | 27 | 28 | @register.inclusion_tag('tradeBOT/user_primary.html') 29 | def get_user_primary_coins(user_exchange, primary_coin): 30 | try: 31 | umcp = UserMainCoinPriority.objects.get(user_exchange=user_exchange, main_coin=primary_coin) 32 | return {'coin': umcp, 33 | 'success': True} 34 | except UserMainCoinPriority.DoesNotExist: 35 | return {'success': False} 36 | 37 | 38 | @register.inclusion_tag('tradeBOT/get_primary_pairs.html') 39 | def get_primary_pairs(coin, user_exchange): 40 | try: 41 | pairs = Pair.objects.filter(main_coin=coin, second_coin__rank__lte=100).order_by('is_active', 42 | 'second_coin__symbol') 43 | return {'pairs': pairs, 'user_exchange': user_exchange} 44 | except Pair.DoesNotExist: 45 | return None 46 | 47 | 48 | @register.filter(name='get_last') 49 | def get_last(pair, user_exchange): 50 | # return 0 51 | max_pk = ExchangeTicker.objects.filter(exchange_id=user_exchange.exchange.pk, pair_id=pair.pk).order_by( 52 | '-id').first().pk 53 | ticker = ExchangeTicker.objects.get(pk=max_pk).last 54 | if ticker is not None: 55 | return round(ticker, 8) 56 | else: 57 | return 0 58 | 59 | 60 | @register.filter(name='get_change_percent') 61 | def get_change_percent(pair, user_exchange): 62 | # return 0 63 | max_pk = ExchangeTicker.objects.filter(exchange_id=user_exchange.exchange.pk, pair_id=pair.pk).order_by( 64 | '-id').first().pk 65 | ticker = ExchangeTicker.objects.get(pk=max_pk).percent_change 66 | if ticker is not None: 67 | return round(ticker * 100, 2) 68 | else: 69 | return 0 70 | 71 | 72 | @register.filter(name='is_pair_active') 73 | def is_pair_active(user_pair, user_exchange_pk): 74 | main_coin = user_pair.pair.main_coin 75 | try: 76 | exch_primary = ExchangeMainCoin.objects.get(coin=main_coin) 77 | user_primary_coin = UserMainCoinPriority.objects.get(user_exchange_id=user_exchange_pk, main_coin=exch_primary) 78 | return user_primary_coin.is_active 79 | except ExchangeMainCoin.DoesNotExist: 80 | return False 81 | except UserMainCoinPriority.DoesNotExist: 82 | return True 83 | 84 | 85 | @register.filter(name='user_pair_rate_of_change') 86 | def user_pair_rate_of_change(user_pair_pk): 87 | try: 88 | user_pair = UserPair.objects.get(pk=user_pair_pk) 89 | return user_pair.rate_of_change 90 | except UserPair.DoesNotExist: 91 | return float(0) 92 | 93 | 94 | @register.filter(name='user_pair_interval_change') 95 | def user_pair_interval_change(user_pair_pk): 96 | try: 97 | user_pair = UserPair.objects.get(pk=user_pair_pk) 98 | return user_pair.change_interval 99 | except UserPair.DoesNotExist: 100 | return 0 101 | 102 | 103 | @register.filter(name='multiple') 104 | def multiple(value, factor): 105 | return value * factor 106 | 107 | 108 | @register.filter(name='haven_percent') 109 | def haven_percent(coin, ue): 110 | try: 111 | user_balance = UserBalance.objects.get(ue=ue, coin=coin.symbol.lower()) 112 | coin_total_btc = user_balance.btc_value 113 | except UserBalance.DoesNotExist: 114 | coin_total_btc = 0 115 | return coin_total_btc / (ue.total_btc / 100) 116 | -------------------------------------------------------------------------------- /tradeBOT/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /tradeBOT/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.decorators import login_required 2 | from django.db.models import Sum, Max, Min 3 | from django.http import HttpResponse 4 | from django.shortcuts import render, redirect 5 | from trade.models import UserExchange, Exchanges 6 | from tradeBOT.models import ExchangeCoin, Pair, ExchangeMainCoin, UserMainCoinPriority, UserPair, ToTrade, \ 7 | UserCoinShare, UserOrder 8 | 9 | 10 | @login_required 11 | def setup(request, pk): 12 | args = {} 13 | try: 14 | args['user_exchange'] = UserExchange.objects.get(pk=pk) 15 | # args['user_exchange'] = UserExchange.objects.get(pk=pk, user=request.user) 16 | # args['user_pairs'] = UserPair.objects.filter(user=request.user, 17 | # user_exchange=args['user_exchange']).order_by( 18 | # '-rank') 19 | args['user_pairs'] = UserPair.objects.filter(user_exchange=args['user_exchange']).order_by( 20 | '-rank') 21 | args['primary_coins'] = ExchangeMainCoin.objects.filter(coin__exchange=args['user_exchange'].exchange).order_by( 22 | 'coin__symbol') 23 | args['to_trade'] = ToTrade.objects.filter(user_pair__user_exchange=args['user_exchange']).order_by( 24 | 'date_updated') 25 | args['orders'] = UserOrder.objects.filter(ue=args['user_exchange']) 26 | args['user_coins'] = UserCoinShare.objects.filter(user_exchange=args['user_exchange']) 27 | except UserExchange.DoesNotExist: 28 | return redirect('index') 29 | return render(request, 'tradeBOT/setup.html', args) 30 | 31 | 32 | def add_user_pair(request): 33 | if request.method == 'POST': 34 | pair_pk = request.POST.get('pair') 35 | user_exchange_pk = request.POST.get('user-exchange') 36 | try: 37 | pair = Pair.objects.get(pk=pair_pk) 38 | UserPair.objects.get_or_create(user=request.user, pair=pair, user_exchange_id=user_exchange_pk) 39 | UserCoinShare.objects.get_or_create(user_exchange_id=user_exchange_pk, coin=pair.second_coin) 40 | except Pair.DoesNotExist: 41 | pass 42 | return redirect('/trade/setup/' + str(user_exchange_pk) + '/') 43 | 44 | 45 | def change_rank(request): 46 | if request.is_ajax(): 47 | pair_id = request.POST.get('pair_id') 48 | type_c = request.POST.get('type') 49 | try: 50 | user_pair = UserPair.objects.get(pk=pair_id, user=request.user) 51 | if type_c == 'up': 52 | user_pair.rank = user_pair.rank + 1 53 | user_pair.save() 54 | elif type_c == 'down': 55 | if user_pair.rank > 1: 56 | user_pair.rank = user_pair.rank - 1 57 | user_pair.save() 58 | except UserPair.DoesNotExist: 59 | return HttpResponse('false', status=200) 60 | return HttpResponse('ok', status=200) 61 | 62 | 63 | def set_share(request): 64 | user_coin_id = request.POST.get('coin') 65 | share = request.POST.get('share') 66 | user_exchange_pk = request.POST.get('user-exchange') 67 | if float(share) < 0: 68 | return HttpResponse('Invalid request', status=200) 69 | if float(share) == 0: 70 | try: 71 | user_coin = UserCoinShare.objects.get(pk=user_coin_id, user_exchange_id=user_exchange_pk, 72 | user_exchange__user=request.user) 73 | user_coin.share = 0 74 | user_coin.save() 75 | except UserCoinShare.DoesNotExist: 76 | return HttpResponse('Not your coin', status=200) 77 | return HttpResponse('ok', status=200) 78 | user_coin_share_summ = \ 79 | UserCoinShare.objects.filter(user_exchange__user=request.user, user_exchange_id=user_exchange_pk).exclude( 80 | pk=user_coin_id).aggregate( 81 | Sum('share'))['share__sum'] 82 | if user_coin_share_summ is None: 83 | user_coin_share_summ = 0 84 | if float(user_coin_share_summ) + float(share) > 100: 85 | return HttpResponse('Sum shares cant be more than 100', status=200) 86 | try: 87 | user_coin = UserCoinShare.objects.get(pk=user_coin_id, user_exchange__user=request.user) 88 | user_coin.share = share 89 | user_coin.save() 90 | except UserCoinShare.DoesNotExist: 91 | return HttpResponse('Not your coin', status=200) 92 | return redirect('/trade/setup/' + str(user_exchange_pk) + '/') 93 | 94 | 95 | def delete_user_pair(request): 96 | if request.is_ajax(): 97 | user_pair_id = request.POST.get('pair_id') 98 | try: 99 | user_pair = UserPair.objects.get(pk=user_pair_id, user=request.user) 100 | user_pairs_with_this_coin = UserPair.objects.filter(pair__second_coin=user_pair.pair.second_coin) 101 | if len(user_pairs_with_this_coin) == 1: 102 | UserCoinShare.objects.get(coin=user_pair.pair.second_coin, 103 | user_exchange=user_pair.user_exchange).delete() 104 | user_pair.delete() 105 | except UserPair.DoesNotExist: 106 | return HttpResponse('Not your pair', status=200) 107 | return HttpResponse('ok', status=200) 108 | 109 | 110 | def relations(request): 111 | args = {'exchanges': Exchanges.objects.all()} 112 | return render(request, 'tradeBOT/relations.html', args) 113 | 114 | 115 | def change_user_exchange_script_activity(request): 116 | if request.is_ajax(): 117 | user_exch_id = request.POST.get('user_exch') 118 | try: 119 | user_exch = UserExchange.objects.get(pk=user_exch_id, user=request.user) 120 | user_exch.is_active_script = not user_exch.is_active_script 121 | user_exch.save() 122 | return HttpResponse('true', status=200) 123 | except UserExchange.DoesNotExist: 124 | return HttpResponse('false', status=200) 125 | 126 | 127 | def change_primary_coin(request): 128 | if request.is_ajax(): 129 | user_exch_pk = request.POST.get('user_exch') 130 | ue = UserExchange.objects.get(pk=user_exch_pk) 131 | coin_pk = request.POST.get('coin') 132 | coin = ExchangeMainCoin.objects.get(pk=coin_pk) 133 | try: 134 | user_primary_coin = UserMainCoinPriority.objects.get(user_exchange=ue, main_coin=coin) 135 | user_primary_coin.is_active = not user_primary_coin.is_active 136 | user_primary_coin.save() 137 | except UserMainCoinPriority.DoesNotExist: 138 | new_user_primary_coin = UserMainCoinPriority() 139 | new_user_primary_coin.main_coin = coin 140 | new_user_primary_coin.priority = 1 141 | new_user_primary_coin.user_exchange = ue 142 | new_user_primary_coin.is_active = False 143 | new_user_primary_coin.save() 144 | return HttpResponse('ok', status=200) 145 | 146 | 147 | def change_primary_coin_rank(request): 148 | if request.is_ajax(): 149 | type_r = request.POST.get('type') 150 | ue_pk = request.POST.get('user_exch') 151 | coin_pk = request.POST.get('coin') 152 | ue = UserExchange.objects.get(pk=ue_pk) 153 | coin = ExchangeMainCoin.objects.get(pk=coin_pk) 154 | try: 155 | user_primary_coin = UserMainCoinPriority.objects.get(user_exchange=ue, main_coin=coin) 156 | if type_r == 'up': 157 | user_primary_coin.priority += 1 158 | elif type_r == 'down': 159 | if user_primary_coin.priority > 1: 160 | user_primary_coin.priority -= 1 161 | user_primary_coin.save() 162 | except UserMainCoinPriority.DoesNotExist: 163 | new_user_primary_coin = UserMainCoinPriority() 164 | new_user_primary_coin.main_coin = coin 165 | if type_r == 'up': 166 | new_user_primary_coin.priority = 2 167 | else: 168 | new_user_primary_coin.priority = 1 169 | new_user_primary_coin.user_exchange = ue 170 | new_user_primary_coin.is_active = True 171 | new_user_primary_coin.save() 172 | return HttpResponse('ok', status=200) 173 | 174 | 175 | def set_pair_add(request): 176 | if request.method == 'POST': 177 | pair_pk = request.POST.get('pair-pk') 178 | user_exchange_pk = request.POST.get('user-exchange-pk') 179 | rate_of_change = request.POST.get('rate_of_change') 180 | if rate_of_change == '': 181 | rate_of_change = 0 182 | try: 183 | UserPair.objects.filter(pk=pair_pk, user_exchange_id=user_exchange_pk).update( 184 | rate_of_change=rate_of_change) 185 | except UserPair.DoesNotExist: 186 | pass 187 | return redirect('/trade/setup/' + str(user_exchange_pk) + '/') 188 | else: 189 | return redirect('/') 190 | 191 | 192 | def get_new_to_trade(request): 193 | if request.is_ajax(): 194 | ue_pk = request.POST.get('user_exch') 195 | already = request.POST.get('already') 196 | to_trade = ToTrade.objects.filter(user_pair__user_exchange_id=ue_pk) 197 | if len(to_trade) != int(already): 198 | return render(request, 'tradeBOT/to_trade.html', {'to_trade': to_trade}) 199 | else: 200 | return HttpResponse('ok', status=200) 201 | 202 | 203 | def exchange_depth_to_trade(request): 204 | if request.method == 'POST': 205 | depth = request.POST.get('depth') 206 | exchange_pk = request.POST.get('user-exchange-pk') 207 | if depth == '': 208 | depth = 0 209 | try: 210 | ue = UserExchange.objects.get(user=request.user, pk=exchange_pk) 211 | ue.coefficient_of_depth = depth 212 | ue.save() 213 | except UserExchange.DoesNotExist: 214 | pass 215 | return redirect('/trade/setup/' + str(exchange_pk) + '/') 216 | else: 217 | return HttpResponse('Please use POST request', status=200) 218 | -------------------------------------------------------------------------------- /user_profile/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/user_profile/__init__.py -------------------------------------------------------------------------------- /user_profile/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /user_profile/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UserProfileConfig(AppConfig): 5 | name = 'user_profile' 6 | -------------------------------------------------------------------------------- /user_profile/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OnGridSystems/CATEd/5023b4a271fa8dab2352e9981fca02d0d133d1f2/user_profile/migrations/__init__.py -------------------------------------------------------------------------------- /user_profile/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /user_profile/templates/user_profile/profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'trade/base.html' %} 2 | {% block content %} 3 |

    Мой профиль

    4 |
    5 |
    6 |
    7 |
    Complete your user profile to increase your limits.
    8 | 30 |
    31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | {% for item in user_exchanges %} 42 | 43 | 44 | 45 | 55 | 65 | 66 | {% endfor %} 67 | 68 |
    БиржаКлючВключенаКорректна
    {{ item.exchange.exchange }}{{ item.apikey | truncatechars:20 }} 46 | {% if item.is_active == True %} 47 | 49 | {% else %} 50 | 52 | 53 | {% endif %} 54 | 56 | {% if item.is_correct == True %} 57 | 59 | {% else %} 60 | 62 | 63 | {% endif %} 64 |
    69 |
    Всего бирж: {{ user_exchanges | length }}
    70 |
    Из них активных: {{ user_active_exchanges | length }}
    71 | 72 | 73 |
    74 |
    75 |
    76 |
    77 | {% endblock %} -------------------------------------------------------------------------------- /user_profile/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /user_profile/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from trade.models import UserExchange 3 | from django.shortcuts import render 4 | 5 | 6 | # Create your views here. 7 | def profile(request): 8 | args = {'user': request.user} 9 | args['user_exchanges'] = UserExchange.objects.filter(user=args['user']) 10 | args['user_active_exchanges'] = args['user_exchanges'].filter(is_active=True) 11 | if request.POST: 12 | first_name = request.POST.get('firstname') 13 | last_name = request.POST.get('lastname') 14 | if first_name is not None: 15 | args['user'].first_name = first_name 16 | if last_name is not None: 17 | args['user'].last_name = last_name 18 | if last_name or first_name: 19 | args['user'].save() 20 | return render(request, 'user_profile/profile.html', args) 21 | --------------------------------------------------------------------------------