|
@@ -1,9 +1,9 @@
|
|
-import datetime
|
|
|
|
import random
|
|
import random
|
|
import re
|
|
import re
|
|
import sqlite3 as db
|
|
import sqlite3 as db
|
|
import sys
|
|
import sys
|
|
import uuid
|
|
import uuid
|
|
|
|
+from datetime import timedelta, datetime
|
|
from math import floor
|
|
from math import floor
|
|
|
|
|
|
import db_setup
|
|
import db_setup
|
|
@@ -370,7 +370,7 @@ def sell_ordered_amount(user_id, ownable_id):
|
|
# return 0
|
|
# return 0
|
|
|
|
|
|
cursor.execute('''
|
|
cursor.execute('''
|
|
- SELECT SUM(orders.ordered_amount - orders.executed_amount)
|
|
|
|
|
|
+ SELECT COALESCE(SUM(orders.ordered_amount - orders.executed_amount),0)
|
|
FROM orders, ownership
|
|
FROM orders, ownership
|
|
WHERE ownership.rowid = orders.ownership_id
|
|
WHERE ownership.rowid = orders.ownership_id
|
|
AND ownership.user_id = ?
|
|
AND ownership.user_id = ?
|
|
@@ -384,6 +384,10 @@ def sell_ordered_amount(user_id, ownable_id):
|
|
def user_owns_at_least(amount, user_id, ownable_id):
|
|
def user_owns_at_least(amount, user_id, ownable_id):
|
|
connect()
|
|
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()
|
|
|
|
+
|
|
cursor.execute('''
|
|
cursor.execute('''
|
|
SELECT rowid
|
|
SELECT rowid
|
|
FROM ownership
|
|
FROM ownership
|
|
@@ -544,10 +548,14 @@ def execute_orders(ownable_id):
|
|
AND (buy_order."limit" IS NULL
|
|
AND (buy_order."limit" IS NULL
|
|
OR sell_order."limit" IS NULL
|
|
OR sell_order."limit" IS NULL
|
|
OR (sell_order."limit" < buy_order."limit"
|
|
OR (sell_order."limit" < buy_order."limit"
|
|
- AND sell_order.stop_loss IS NULL
|
|
|
|
- AND buy_order.stop_loss IS NULL))
|
|
|
|
- ORDER BY COALESCE(sell_order."limit", 0) ASC,
|
|
|
|
- -COALESCE(buy_order."limit", 0) ASC
|
|
|
|
|
|
+ AND NOT sell_order.stop_loss
|
|
|
|
+ AND NOT buy_order.stop_loss))
|
|
|
|
+ ORDER BY CASE WHEN sell_order."limit" IS NULL THEN 0 ELSE 1 END ASC,
|
|
|
|
+ CASE WHEN buy_order."limit" IS NULL THEN 0 ELSE 1 END ASC,
|
|
|
|
+ buy_order."limit" DESC,
|
|
|
|
+ sell_order."limit" ASC,
|
|
|
|
+ buy_order.ordered_amount - buy_order.executed_amount DESC,
|
|
|
|
+ sell_order.ordered_amount - sell_order.executed_amount DESC
|
|
LIMIT 1
|
|
LIMIT 1
|
|
''', (ownable_id, ownable_id,))
|
|
''', (ownable_id, ownable_id,))
|
|
|
|
|
|
@@ -561,22 +569,23 @@ def execute_orders(ownable_id):
|
|
|
|
|
|
# TODO continue and delete order if buyer has not enough money
|
|
# TODO continue and delete order if buyer has not enough money
|
|
|
|
|
|
- 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
|
|
|
|
-
|
|
|
|
- if not isinstance(buy_limit, str) and not isinstance(buy_limit, float):
|
|
|
|
- return AssertionError()
|
|
|
|
- if not isinstance(sell_limit, str) and not isinstance(sell_limit, float):
|
|
|
|
- return AssertionError()
|
|
|
|
|
|
+ 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
|
|
|
|
|
|
- if buy_limit == '' and sell_limit == '':
|
|
|
|
- raise AssertionError()
|
|
|
|
- elif buy_limit == '':
|
|
|
|
|
|
+ if buy_limit is None and sell_limit is None:
|
|
|
|
+ raise AssertionError() # TODO find a solution
|
|
|
|
+ elif buy_limit is None:
|
|
price = sell_limit
|
|
price = sell_limit
|
|
- elif sell_limit == '':
|
|
|
|
|
|
+ elif sell_limit is None:
|
|
price = buy_limit
|
|
price = buy_limit
|
|
else: # both not NULL
|
|
else: # both not NULL
|
|
price = (float(sell_limit) + float(buy_limit)) / 2
|
|
price = (float(sell_limit) + float(buy_limit)) / 2
|
|
|
|
|
|
|
|
+ if price == 0:
|
|
|
|
+ raise AssertionError() # TODO find a solution
|
|
|
|
+
|
|
buyer_money = user_money(buyer_id)
|
|
buyer_money = user_money(buyer_id)
|
|
|
|
|
|
amount = min(buy_order_amount - buy_executed_amount,
|
|
amount = min(buy_order_amount - buy_executed_amount,
|
|
@@ -584,13 +593,13 @@ def execute_orders(ownable_id):
|
|
floor(buyer_money / price))
|
|
floor(buyer_money / price))
|
|
|
|
|
|
buy_order_finished = (buy_order_amount - buy_executed_amount - amount <= 0) or (
|
|
buy_order_finished = (buy_order_amount - buy_executed_amount - amount <= 0) or (
|
|
- buyer_money - amount * price < price)
|
|
|
|
|
|
+ buyer_money - amount * price < price)
|
|
sell_order_finished = (sell_order_amount - sell_executed_amount - amount <= 0)
|
|
sell_order_finished = (sell_order_amount - sell_executed_amount - amount <= 0)
|
|
|
|
|
|
if price < 0 or amount <= 0:
|
|
if price < 0 or amount <= 0:
|
|
return AssertionError()
|
|
return AssertionError()
|
|
|
|
|
|
- # actually execute the order, but the bank does not send or recieve anything
|
|
|
|
|
|
+ # actually execute the order, but the bank does not send or receive anything
|
|
if buyer_id != bank_id(): # buyer pays
|
|
if buyer_id != bank_id(): # buyer pays
|
|
cursor.execute('''
|
|
cursor.execute('''
|
|
UPDATE ownership
|
|
UPDATE ownership
|
|
@@ -617,6 +626,8 @@ def execute_orders(ownable_id):
|
|
WHERE user_id = ?
|
|
WHERE user_id = ?
|
|
AND ownable_id = ?
|
|
AND ownable_id = ?
|
|
''', (amount, seller_id, currency_id()))
|
|
''', (amount, seller_id, currency_id()))
|
|
|
|
+
|
|
|
|
+ # update order execution state
|
|
cursor.execute('''
|
|
cursor.execute('''
|
|
UPDATE orders
|
|
UPDATE orders
|
|
SET executed_amount = executed_amount + ?
|
|
SET executed_amount = executed_amount + ?
|
|
@@ -640,9 +651,10 @@ def execute_orders(ownable_id):
|
|
if buyer_id != seller_id:
|
|
if buyer_id != seller_id:
|
|
cursor.execute('''
|
|
cursor.execute('''
|
|
UPDATE orders
|
|
UPDATE orders
|
|
- SET stop_loss = NULL
|
|
|
|
|
|
+ SET stop_loss = NULL,
|
|
"limit" = NULL
|
|
"limit" = NULL
|
|
- WHERE stop_loss
|
|
|
|
|
|
+ WHERE stop_loss IS NOT NULL
|
|
|
|
+ AND stop_loss
|
|
AND (buy AND "limit" > ?)
|
|
AND (buy AND "limit" > ?)
|
|
OR (NOT buy AND "limit" < ?)
|
|
OR (NOT buy AND "limit" < ?)
|
|
''', (price, price,))
|
|
''', (price, price,))
|
|
@@ -688,10 +700,19 @@ def bank_order(buy, ownable_id, limit, amount, time_until_expiration):
|
|
''', ('External investors are selling ' + ownable_name + ' atm',))
|
|
''', ('External investors are selling ' + ownable_name + ' atm',))
|
|
|
|
|
|
|
|
|
|
-def place_order(buy, ownership_id, limit, stop_loss, amount, time_until_expiration):
|
|
|
|
|
|
+def current_time(): # might differ from datetime.datetime.now() for time zone reasons
|
|
connect()
|
|
connect()
|
|
|
|
|
|
- expiry = datetime.datetime.now() + datetime.timedelta(minutes=time_until_expiration)
|
|
|
|
|
|
+ cursor.execute('''
|
|
|
|
+ SELECT datetime('now')
|
|
|
|
+ ''')
|
|
|
|
+
|
|
|
|
+ return cursor.fetchone()[0]
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def place_order(buy, ownership_id, limit, stop_loss, amount, time_until_expiration):
|
|
|
|
+ connect()
|
|
|
|
+ expiry = datetime.strptime(current_time(), '%Y-%m-%d %H:%M:%S') + timedelta(minutes=time_until_expiration)
|
|
|
|
|
|
cursor.execute('''
|
|
cursor.execute('''
|
|
INSERT INTO orders
|
|
INSERT INTO orders
|