Skip to content

Commit ade3ac7

Browse files
committed
Add documentation on deployment
1 parent eb73654 commit ade3ac7

File tree

2 files changed

+272
-0
lines changed

2 files changed

+272
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ to
141141
check_request_enabled = Signal('request')
142142

143143

144+
## Deployment on pythonanywhere
145+
146+
[Here](https://github.com/VikSil/howtoquant-backend/blob/trunk/howtoquant/docs/deployment.md) is a tutorial on how to deploy this project on pythonanywhere web-hosting service.
147+
148+
144149
## Past sprints
145150

146151
Code and release notes of each of the past releases can be found in the respective branch of this repo, as per table below.

howtoquant/docs/deployment.md

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
# Deployment instructions
2+
3+
This manual contains instructions on how to deploy the repo on pythonanywhere hosting service. For full functionality always-on script are required to run microservices via cron jobs. Always-on scripts are a paid-for feature of pythonanywhere. The minimum custom bundle allows for one always-on script, one website, 2000s CPU per 24 hours and 1 GB of disk storage, at the price of 5 USD per month. This should be sufficient to host a fully functional version of this website.
4+
5+
For the purposes of this manual it is assumed that the pythonanywhere username is "*__howtoquant__*"
6+
7+
Some of the information in this manual is from [this](https://www.youtube.com/watch?v=xtnUwvjOThg) useful tutorial, with some project-specific details added.
8+
9+
## Setting up the repo
10+
11+
1. On pythonanywhere **Dashboard**, click `$Bash` button in the `New console section`. This will open a new Bash console.
12+
1. Clone the repository into pythonanywhere with this command:
13+
14+
git clone https://github.com/VikSil/howtoquant-backend
15+
16+
At this point the usage should be around 3s CPU and 14MB of storage.
17+
18+
3. Create vitrual environment with this command:
19+
20+
mkvirtualenv --python=/usr/bin/python3.10 venv
21+
22+
At this point the usage should be around 41s CPU and 70MB of storage.
23+
24+
4. Navigate into the project directory with this command:
25+
26+
cd how*
27+
28+
5. Install all of the project dependencies with this command (this will take 5-10 minutes to complete):
29+
30+
pip install -r requirements.txt
31+
32+
At this point the usage should be around 100s CPU and 370MB of storage.
33+
34+
## Creating Web application
35+
36+
1. Open pythonanywhere **Web** dashboard.
37+
1. Click on `Add a new web app` button.
38+
1. Choose the default domain name and click `Next` (domain name is configured on the front-end side via Netlify).
39+
1. Choose **Manual configuration** - the screen will change.
40+
1. Choose **Python 3.10** - the screen will change.
41+
1. Click `Next` button - the Web dashboard will open.
42+
1. In the `Virtualenv` section of the Web dashboard add path to virtualenv. Click the red link, type `venv` into the box and confirm.
43+
1. In the `Code` section above click on the **WSGI configuration file** link - the file will open
44+
1. Replace the content of the file with the following code
45+
46+
import os
47+
import sys
48+
49+
path = '/home/howtoquant/howtoquant-backend'
50+
if path not in sys.path:
51+
sys.path.append(path)
52+
53+
os.environ['DJANGO_SETTINGS_MODULE'] = 'howtoquant.settings'
54+
55+
from django.core.wsgi import get_wsgi_application
56+
application = get_wsgi_application()
57+
58+
1. Click `Save` button.
59+
60+
## Adding configuration and monkey-fixes
61+
62+
1. In venv console execute the following commands:
63+
64+
cd how*
65+
mkdir logs
66+
mkdir .envs
67+
cd .envs
68+
touch .env_prod
69+
nano .env_prod
70+
71+
1. In the editing screen that will open, paste the environment variables.
72+
ENVIRONMENT=production
73+
74+
DB_ENGINE=django.db.backends.mysql
75+
DB_NAME=howtoquant$[database]
76+
DB_USER=howtoquant
77+
DB_PASSWORD=[password]
78+
DB_HOST=howtoquant.mysql.pythonanywhere-services.com
79+
DB_PORT=3306
80+
81+
POLYGON_API_KEY=[api_key]
82+
83+
SECRET_KEY=[secret_key]
84+
85+
1. Press `Ctrl + X`, then `Y`, then `Enter`.
86+
1. Execute the following commands:
87+
88+
cd ..
89+
nano settings.py
90+
91+
1. In the editing screen that will open:
92+
93+
* switch line
94+
95+
env.read_env(BASE_DIR /'howtoquant/.envs/.env_dev')
96+
97+
to
98+
99+
env.read_env(BASE_DIR /'howtoquant/.envs/.env_prod')
100+
101+
* switch line
102+
103+
ALLOWED_HOSTS = []
104+
105+
to
106+
107+
ALLOWED_HOSTS = ["127.0.0.1",
108+
'howtoquant.mysql.pythonanywhere-services.com',
109+
'howtoquant.pythonanywhere.com']
110+
111+
* comment out line
112+
113+
CORS_ALLOWED_ORIGINS = ['http://localhost:5173',]
114+
115+
and uncomment
116+
117+
CORS_ORIGIN_ALLOW_ALL = True
118+
119+
6. Press `Ctrl + X`, then `Y`, then `Enter`.
120+
121+
1. Execute the following commands:
122+
123+
cd ~
124+
cd .virtualenvs/venv/lib/python3.10/site-packages/corsheaders
125+
nano checks.py
126+
127+
1. In the editing screen that will open switch line
128+
129+
from collections import Sequence
130+
131+
to
132+
133+
from collections.abc import Sequence
134+
135+
1. Press `Ctrl + X`, then `Y`, then `Enter`.
136+
137+
1. Execute the following command:
138+
139+
nano signals.py
140+
141+
1. In the editing screen that will open switch line
142+
143+
check_request_enabled = Signal(providing_args=['request'])
144+
145+
to
146+
147+
check_request_enabled = Signal('request')
148+
149+
1. Press `Ctrl + X`, then `Y`, then `Enter`.
150+
151+
## Creating and seeding the database
152+
153+
1. Open pythonanywhere **Databases** dashboard.
154+
1. If you have previously created a database for the website, you will need to reset it (otherwise, proceed to step 4.). Click on the database name in the `Your databases` section - MySQL console will open.
155+
1. Drop the database with the following query, where [database] is the database name. These will be identical to the link that you clicked in the previous step.
156+
157+
drop database howtoquant$[database]
158+
159+
1. In `Create database` section of **Databases** dashboard, enter a new database name and click `Create` button. The new database will appear in the list above.
160+
1. Click on the database name in the `Your databases` section - MySQL console will open.
161+
1. Switch back to the venv Bash console and run the following commands:
162+
163+
cd ~
164+
cd how*
165+
python manage.py migrate
166+
167+
1. Switch back to the MySQL console and run in the contents of vanilla scripts in the following sequence:
168+
169+
* classifiers\db\db_setup_classifiers.sql
170+
* classifiers\db\vanilla_seed_classifiers.sql
171+
* staticdata\db\db_setup_staticdata.sql
172+
* staticdata\db\vanilla_seed_staticdata.sql
173+
* marketdata\db\db_setup_marketdata.sql
174+
* marketdata\db\vanilla_seed_marketdata.sql
175+
* accounting\db\db_setup_accounting.sql
176+
* accounting\db\vanilla_seed_accounting.sql
177+
* config\db\db_setup_config.sql
178+
179+
## Setting up always-on script
180+
181+
1. Open pythonanywhere **Tasks** dashboard.
182+
1. In the `Always-on tasks` section add a new always-on task:
183+
184+
source /home/howtoquant/.virtualenvs/venv/bin/activate && cd how* && python manage.py runcrons
185+
186+
1. Click `Create` button.
187+
1. Click on the `View task log` button (first in `Actions` column) - this will open the log file.
188+
1. After the script has started, it should continously log every 60 seconds output similar to:
189+
190+
Sep 2 22:57:55 Running Crons
191+
Sep 2 22:57:55 ========================================
192+
Sep 2 22:57:55 [✔] config.rollforward
193+
Sep 2 22:57:55 [✘] config.flow_booker
194+
Sep 2 22:57:55 [✔] config.position_manager
195+
Sep 2 22:57:55 [✔] config.cash_manager
196+
Sep 2 22:57:55 [✔] config.asset_manager
197+
198+
## Final step
199+
200+
Once all of the above are done, click the big, green `Reload` button on the Web dashboard and wait for it to reload.
201+
202+
## Post-deployment tests
203+
204+
1. Run the following queries in the MySQL console:
205+
206+
SELECT * FROM staticdata_identifier; -- should return three tickers
207+
SELECT * FROM config_msg_queue; -- should return an empty set
208+
209+
1. Navigate to `https://howtoquant.pythonanywhere.com/accounting/api/asset_ladder` - this should return a JSON with status `OK` and `null` dataset on `asset_ladder` key.
210+
211+
1. Navigate to `https://howtoquant.pythonanywhere.com/accounting/api/cash_ladder?end_date=[date]`, where [date] is T+2 in format YYYY-MM-DD - this should return a JSON with status `OK` and `null` dataset on `asset_ladder` key.
212+
213+
1. Navigate to `https://howtoquant.pythonanywhere.com/classifiers/api/countries` - this should return a JSOn with a list of active countries.
214+
215+
1. Navigate to `https://howtoquant.pythonanywhere.com/staticdata/api/equities` - this should return a JSON with three equities.
216+
217+
1. Send a PUT request to `https://howtoquant.pythonanywhere.com//staticdata/api/instruments` with the following body:
218+
219+
{
220+
"ticker":"NVDA",
221+
"service":"polygon.io"
222+
}
223+
224+
1. Navigate to `https://howtoquant.pythonanywhere.com/staticdata/api/equities` - this should now return a JSON with four equities, including NVDIA.
225+
226+
1. Send a PUT request to `https://howtoquant.pythonanywhere.com/marketdata/api/prices/new` with the following body:
227+
228+
{
229+
"tickers":["NVDA"],
230+
"date_from": "2024-08-01",
231+
"date_to": "2024-09-01"
232+
}
233+
234+
this should return a download_id.
235+
236+
1. Send a PUT request to `https://howtoquant.pythonanywhere.com/marketdata/api/prices/download` with the following body:
237+
238+
{
239+
"download_id": [download_id from the previous step],
240+
"options":"overrideall"
241+
}
242+
243+
this should return result "OK"
244+
245+
1. Navigate to `https://howtoquant.pythonanywhere.com/marketdata/api/prices` - this should return a JSON with the saved prices
246+
247+
1. Send a PUT request to `https://howtoquant.pythonanywhere.com/accounting/api/trades` with the following body:
248+
249+
{
250+
"ticker":"TSLA",
251+
"direction":"B",
252+
"quantity": 10,
253+
"price":200,
254+
"book_name": "Long Short",
255+
"strategy_name": "Long Only",
256+
"counterparty": "Counterparty"
257+
}
258+
259+
this should return trade details
260+
261+
1. Navigate to `https://howtoquant.pythonanywhere.com/accounting/api/trades` - this should return a JSON with the saved trade
262+
263+
1. Wait for up to 10 minutes for the services to process the trade into ladders.
264+
265+
1. Navigate to `https://howtoquant.pythonanywhere.com/accounting/api/asset_ladder` - this should now return a JSON with a new record in the ladder.
266+
267+
1. Navigate to `https://howtoquant.pythonanywhere.com/accounting/api/cash_ladder?end_date=[date]`, where [date] is T+2 in format YYYY-MM-DD - this should now return a JSON with a new record in the ladder.

0 commit comments

Comments
 (0)