-
Notifications
You must be signed in to change notification settings - Fork 0
/
process_orders.py
39 lines (32 loc) · 1.48 KB
/
process_orders.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from sqlalchemy.orm import Session
from db import engine, OrderModel, OrderStatus
import time
import requests
from sqlalchemy import and_
from sqlalchemy.orm import query
import logging
logging.basicConfig(level=logging.INFO)
def btc_price():
btc_price_api_response = requests.get('http://127.0.0.1:5000/btc-price')
return btc_price_api_response.json()["price"]
while True:
with Session(engine) as session:
try:
latest_btc_price = btc_price()
except Exception as e:
logging.error(f"failed to fetch btc price: {e}")
continue
# We querying and processing the orders one by one in order to make this script
# scalable while maintaining data consistency with transactions (achieved by with_for_update)
order_to_be_filled = session.query(OrderModel).filter(
latest_btc_price < OrderModel.price_limit, OrderModel.status == OrderStatus.waiting).with_for_update().first()
if order_to_be_filled:
order_total_price = order_to_be_filled.amount * latest_btc_price
if order_to_be_filled.account.usd_balance < order_total_price:
continue
order_to_be_filled.account.usd_balance -= order_total_price
order_to_be_filled.account.btc_balance += order_to_be_filled.amount
order_to_be_filled.status = OrderStatus.processed
session.commit()
logging.info(f"Filled order(id): {order_to_be_filled}")
time.sleep(0.1)