|
@@ -4,6 +4,7 @@ import random
|
|
|
import re
|
|
|
import sqlite3 as db
|
|
|
import uuid
|
|
|
+from datetime import datetime
|
|
|
from logging import INFO
|
|
|
from math import floor
|
|
|
from shutil import copyfile
|
|
@@ -120,8 +121,6 @@ def setup():
|
|
|
|
|
|
|
|
|
def used_key_count():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT COUNT(*) -- rarely executed, no index needed, O(n) query
|
|
|
FROM keys
|
|
@@ -179,8 +178,6 @@ def own(user_id, ownable_name, amount=0):
|
|
|
|
|
|
|
|
|
def send_ownable(from_user_id, to_user_id, ownable_id, amount):
|
|
|
- connect()
|
|
|
-
|
|
|
if amount < 0:
|
|
|
raise AssertionError('Can not send negative amount')
|
|
|
|
|
@@ -195,7 +192,7 @@ def send_ownable(from_user_id, to_user_id, ownable_id, amount):
|
|
|
|
|
|
own(to_user_id, ownable_name_by_id(ownable_id))
|
|
|
|
|
|
- if from_user_id != bank_id_ or ownable_id != currency_id():
|
|
|
+ if to_user_id != bank_id_ or ownable_id != currency_id():
|
|
|
execute('''
|
|
|
UPDATE ownership
|
|
|
SET amount = amount + ?
|
|
@@ -206,8 +203,6 @@ def send_ownable(from_user_id, to_user_id, ownable_id, amount):
|
|
|
|
|
|
|
|
|
def valid_key(key):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT key
|
|
|
FROM keys
|
|
@@ -222,8 +217,6 @@ def valid_key(key):
|
|
|
|
|
|
|
|
|
def new_session(user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
session_id = str(uuid.uuid4())
|
|
|
|
|
|
execute('''
|
|
@@ -236,8 +229,6 @@ def new_session(user_id):
|
|
|
|
|
|
|
|
|
def save_key(key):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
INSERT INTO keys
|
|
|
(key)
|
|
@@ -246,8 +237,6 @@ def save_key(key):
|
|
|
|
|
|
|
|
|
def drop_old_sessions():
|
|
|
- connect()
|
|
|
-
|
|
|
execute(''' -- no need to optimize this very well
|
|
|
DELETE FROM sessions
|
|
|
WHERE
|
|
@@ -259,8 +248,6 @@ def drop_old_sessions():
|
|
|
|
|
|
|
|
|
def user_exists(username):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid
|
|
|
FROM users
|
|
@@ -274,8 +261,6 @@ def user_exists(username):
|
|
|
|
|
|
|
|
|
def get_user_id_by_session_id(session_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT users.rowid
|
|
|
FROM sessions, users
|
|
@@ -290,8 +275,6 @@ def get_user_id_by_session_id(session_id):
|
|
|
|
|
|
|
|
|
def get_user_id_by_name(username):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT users.rowid
|
|
|
FROM users
|
|
@@ -302,8 +285,6 @@ def get_user_id_by_name(username):
|
|
|
|
|
|
|
|
|
def get_user_ownership(user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT
|
|
|
ownables.name,
|
|
@@ -340,7 +321,6 @@ def get_user_ownership(user_id):
|
|
|
|
|
|
|
|
|
def activate_key(key, user_id):
|
|
|
- connect()
|
|
|
execute('''
|
|
|
UPDATE keys
|
|
|
SET used_by_user_id = ?
|
|
@@ -352,8 +332,6 @@ def activate_key(key, user_id):
|
|
|
|
|
|
|
|
|
def bank_id():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT users.rowid
|
|
|
FROM users
|
|
@@ -364,8 +342,6 @@ def bank_id():
|
|
|
|
|
|
|
|
|
def valid_session_id(session_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid
|
|
|
FROM sessions
|
|
@@ -379,8 +355,6 @@ def valid_session_id(session_id):
|
|
|
|
|
|
|
|
|
def get_user_orders(user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT
|
|
|
CASE
|
|
@@ -408,8 +382,6 @@ def get_user_orders(user_id):
|
|
|
|
|
|
|
|
|
def get_user_loans(user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT
|
|
|
rowid,
|
|
@@ -425,8 +397,6 @@ def get_user_loans(user_id):
|
|
|
|
|
|
|
|
|
def get_ownable_orders(user_id, ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT
|
|
|
CASE
|
|
@@ -454,8 +424,6 @@ def get_ownable_orders(user_id, ownable_id):
|
|
|
|
|
|
|
|
|
def sell_ordered_amount(user_id, ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT COALESCE(SUM(orders.ordered_amount - orders.executed_amount),0)
|
|
|
FROM orders, ownership
|
|
@@ -469,8 +437,6 @@ def sell_ordered_amount(user_id, ownable_id):
|
|
|
|
|
|
|
|
|
def available_amount(user_id, ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT amount
|
|
|
FROM ownership
|
|
@@ -482,8 +448,6 @@ def available_amount(user_id, ownable_id):
|
|
|
|
|
|
|
|
|
def user_has_at_least_available(amount, user_id, ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
if not isinstance(amount, float) and not isinstance(amount, int):
|
|
|
# comparison of float with strings does not work so well in sql
|
|
|
raise AssertionError()
|
|
@@ -503,13 +467,11 @@ def user_has_at_least_available(amount, user_id, ownable_id):
|
|
|
|
|
|
|
|
|
def news():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT dt, title FROM
|
|
|
(SELECT *, rowid
|
|
|
FROM news
|
|
|
- ORDER BY rowid DESC -- equivalent to order by dt
|
|
|
+ ORDER BY news.rowid DESC -- equivalent to order by dt
|
|
|
LIMIT 20) n
|
|
|
ORDER BY rowid ASC -- equivalent to order by dt
|
|
|
''')
|
|
@@ -518,8 +480,6 @@ def news():
|
|
|
|
|
|
|
|
|
def ownable_name_exists(name):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid
|
|
|
FROM ownables
|
|
@@ -533,8 +493,6 @@ def ownable_name_exists(name):
|
|
|
|
|
|
|
|
|
def new_stock(expiry, name=None):
|
|
|
- connect()
|
|
|
-
|
|
|
while name is None:
|
|
|
name = random_chars(6)
|
|
|
if ownable_name_exists(name):
|
|
@@ -559,13 +517,12 @@ def new_stock(expiry, name=None):
|
|
|
ownable_id,
|
|
|
price,
|
|
|
amount,
|
|
|
- expiry)
|
|
|
+ expiry,
|
|
|
+ ioc=False)
|
|
|
return name
|
|
|
|
|
|
|
|
|
def ownable_id_by_name(ownable_name):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid
|
|
|
FROM ownables
|
|
@@ -576,8 +533,6 @@ def ownable_id_by_name(ownable_name):
|
|
|
|
|
|
|
|
|
def get_ownership_id(ownable_id, user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid
|
|
|
FROM ownership
|
|
@@ -589,8 +544,6 @@ def get_ownership_id(ownable_id, user_id):
|
|
|
|
|
|
|
|
|
def currency_id():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid
|
|
|
FROM ownables
|
|
@@ -601,8 +554,6 @@ def currency_id():
|
|
|
|
|
|
|
|
|
def user_money(user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT amount
|
|
|
FROM ownership
|
|
@@ -614,8 +565,6 @@ def user_money(user_id):
|
|
|
|
|
|
|
|
|
def delete_order(order_id, new_order_status):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
INSERT INTO order_history
|
|
|
(ownership_id, buy, "limit", ordered_amount, executed_amount, expiry_dt, status, order_id)
|
|
@@ -639,8 +588,6 @@ def delete_order(order_id, new_order_status):
|
|
|
|
|
|
|
|
|
def current_value(ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
if ownable_id == currency_id():
|
|
|
return 1
|
|
|
|
|
@@ -654,7 +601,6 @@ def current_value(ownable_id):
|
|
|
|
|
|
|
|
|
def execute_orders(ownable_id):
|
|
|
- connect()
|
|
|
orders_traded = False
|
|
|
while True:
|
|
|
# find order to execute
|
|
@@ -743,8 +689,8 @@ def execute_orders(ownable_id):
|
|
|
else:
|
|
|
break
|
|
|
|
|
|
- buy_ownership_id, _, buy_limit, _, buy_order_amount, buy_executed_amount, buy_expiry_dt, \
|
|
|
- sell_ownership_id, _, sell_limit, _, sell_order_amount, sell_executed_amount, sell_expiry_dt, \
|
|
|
+ _, buy_ownership_id, _, buy_limit, _, buy_order_amount, buy_executed_amount, buy_expiry_dt, _, \
|
|
|
+ _, sell_ownership_id, _, sell_limit, _, sell_order_amount, sell_executed_amount, sell_expiry_dt, _, \
|
|
|
buyer_id, seller_id, buy_order_id, sell_order_id \
|
|
|
= matching_orders
|
|
|
|
|
@@ -773,6 +719,9 @@ def execute_orders(ownable_id):
|
|
|
sell_order_amount - sell_executed_amount,
|
|
|
_my_division(buyer_money, price))
|
|
|
|
|
|
+ if amount < 0:
|
|
|
+ amount = 0
|
|
|
+
|
|
|
if amount == 0: # probable because buyer has not enough money
|
|
|
delete_order(buy_order_id, 'Unable to pay')
|
|
|
continue
|
|
@@ -824,8 +773,6 @@ def execute_orders(ownable_id):
|
|
|
|
|
|
|
|
|
def ownable_id_by_ownership_id(ownership_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT ownable_id
|
|
|
FROM ownership
|
|
@@ -836,8 +783,6 @@ def ownable_id_by_ownership_id(ownership_id):
|
|
|
|
|
|
|
|
|
def ownable_name_by_id(ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT name
|
|
|
FROM ownables
|
|
@@ -847,7 +792,7 @@ def ownable_name_by_id(ownable_id):
|
|
|
return current_cursor.fetchone()[0]
|
|
|
|
|
|
|
|
|
-def bank_order(buy, ownable_id, limit, amount, expiry):
|
|
|
+def bank_order(buy, ownable_id, limit, amount, expiry, ioc):
|
|
|
if not limit:
|
|
|
raise AssertionError('The bank does not give away anything.')
|
|
|
place_order(buy,
|
|
@@ -855,7 +800,8 @@ def bank_order(buy, ownable_id, limit, amount, expiry):
|
|
|
limit,
|
|
|
False,
|
|
|
amount,
|
|
|
- expiry)
|
|
|
+ expiry,
|
|
|
+ ioc=ioc)
|
|
|
ownable_name = ownable_name_by_id(ownable_id)
|
|
|
new_news('External investors are selling ' + ownable_name + ' atm')
|
|
|
|
|
@@ -870,21 +816,31 @@ def current_db_time(): # might differ from datetime.datetime.now() for time zon
|
|
|
return current_cursor.fetchone()[0]
|
|
|
|
|
|
|
|
|
-def place_order(buy, ownership_id, limit, stop_loss, amount, expiry):
|
|
|
+def current_db_timestamp():
|
|
|
connect()
|
|
|
+
|
|
|
execute('''
|
|
|
- INSERT INTO orders
|
|
|
- (buy, ownership_id, "limit", stop_loss, ordered_amount, expiry_dt)
|
|
|
- VALUES (?, ?, ?, ?, ?, ?)
|
|
|
- ''', (buy, ownership_id, limit, stop_loss, amount, expiry))
|
|
|
+ SELECT CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)
|
|
|
+ ''')
|
|
|
+
|
|
|
+ return int(current_cursor.fetchone()[0])
|
|
|
+
|
|
|
+
|
|
|
+def place_order(buy, ownership_id, limit, stop_loss, amount, expiry, ioc: bool):
|
|
|
+ if isinstance(expiry, datetime):
|
|
|
+ expiry = expiry.timestamp()
|
|
|
+ execute(''' INSERT INTO orders
|
|
|
+ (buy, ownership_id, "limit", stop_loss, ordered_amount, expiry_dt, ioc)
|
|
|
+ VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
|
+ ''', (buy, ownership_id, limit, stop_loss, amount, expiry, ioc))
|
|
|
|
|
|
execute_orders(ownable_id_by_ownership_id(ownership_id))
|
|
|
+
|
|
|
+ execute('''DELETE FROM orders WHERE ioc''')
|
|
|
return True
|
|
|
|
|
|
|
|
|
def trades_on(ownable_id, limit):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT datetime(dt,'localtime'), amount, price
|
|
|
FROM transactions
|
|
@@ -897,7 +853,6 @@ def trades_on(ownable_id, limit):
|
|
|
|
|
|
|
|
|
def trades(user_id, limit):
|
|
|
- connect()
|
|
|
execute('''
|
|
|
SELECT
|
|
|
(CASE WHEN seller_id = ? THEN 'Sell' ELSE 'Buy' END),
|
|
@@ -915,11 +870,9 @@ def trades(user_id, limit):
|
|
|
|
|
|
|
|
|
def drop_expired_orders():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid, ownership_id, * FROM orders
|
|
|
- WHERE expiry_dt < DATETIME('now')
|
|
|
+ WHERE expiry_dt < CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)
|
|
|
''')
|
|
|
|
|
|
data = current_cursor.fetchall()
|
|
@@ -940,8 +893,6 @@ def generate_keys(count=1):
|
|
|
|
|
|
|
|
|
def user_has_order_with_id(session_id, order_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT orders.rowid
|
|
|
FROM orders, ownership, sessions
|
|
@@ -958,8 +909,6 @@ def user_has_order_with_id(session_id, order_id):
|
|
|
|
|
|
|
|
|
def leaderboard():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT *
|
|
|
FROM ( -- one score for each user
|
|
@@ -987,8 +936,6 @@ def leaderboard():
|
|
|
|
|
|
|
|
|
def user_wealth(user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT (
|
|
|
SELECT COALESCE(SUM(
|
|
@@ -1015,8 +962,6 @@ def user_wealth(user_id):
|
|
|
|
|
|
|
|
|
def change_password(session_id, password, salt):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
UPDATE users
|
|
|
SET password = ?, salt= ?
|
|
@@ -1025,8 +970,6 @@ def change_password(session_id, password, salt):
|
|
|
|
|
|
|
|
|
def sign_out_user(session_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
DELETE FROM sessions
|
|
|
WHERE user_id = (SELECT user_id FROM sessions s2 WHERE s2.session_id = ?)
|
|
@@ -1034,8 +977,6 @@ def sign_out_user(session_id):
|
|
|
|
|
|
|
|
|
def delete_user(user_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
DELETE FROM sessions
|
|
|
WHERE user_id = ?
|
|
@@ -1069,8 +1010,6 @@ def delete_user(user_id):
|
|
|
|
|
|
|
|
|
def delete_ownable(ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
DELETE FROM transactions
|
|
|
WHERE ownable_id = ?
|
|
@@ -1107,8 +1046,6 @@ def delete_ownable(ownable_id):
|
|
|
|
|
|
|
|
|
def hash_all_users_passwords():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT rowid, password, salt
|
|
|
FROM users
|
|
@@ -1133,7 +1070,6 @@ def hash_all_users_passwords():
|
|
|
|
|
|
|
|
|
def new_news(message):
|
|
|
- connect()
|
|
|
execute('''
|
|
|
INSERT INTO news(title)
|
|
|
VALUES (?)
|
|
@@ -1141,8 +1077,6 @@ def new_news(message):
|
|
|
|
|
|
|
|
|
def abs_spread(ownable_id):
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT
|
|
|
(SELECT MAX("limit")
|
|
@@ -1163,8 +1097,6 @@ def abs_spread(ownable_id):
|
|
|
|
|
|
|
|
|
def ownables():
|
|
|
- connect()
|
|
|
-
|
|
|
execute('''
|
|
|
SELECT name, course,
|
|
|
(SELECT SUM(amount)
|
|
@@ -1199,7 +1131,6 @@ def ownables():
|
|
|
|
|
|
|
|
|
def reset_bank():
|
|
|
- connect()
|
|
|
execute('''
|
|
|
DELETE FROM ownership
|
|
|
WHERE user_id = ?
|
|
@@ -1231,7 +1162,6 @@ def ownable_ids():
|
|
|
|
|
|
|
|
|
def get_old_orders(user_id, include_executed, include_canceled, limit):
|
|
|
- connect()
|
|
|
execute('''
|
|
|
SELECT
|
|
|
(CASE WHEN order_history.buy THEN 'Buy' ELSE 'Sell' END),
|
|
@@ -1296,7 +1226,7 @@ def assign_banking_licence(user_id):
|
|
|
|
|
|
|
|
|
def pay_loan_interest():
|
|
|
- current_dt = execute("SELECT strftime('%s', CURRENT_TIMESTAMP)").fetchone()[0]
|
|
|
+ current_dt = execute("SELECT CAST(strftime('%s', CURRENT_TIMESTAMP) AS INTEGER)").fetchone()[0]
|
|
|
sec_per_year = 3600 * 24 * 365
|
|
|
interests = execute('''
|
|
|
SELECT
|