In [3]:
import numpy as np

from collections import namedtuple

In [4]:
'''
struct to storage order price and volume to trade

Usage:
a = Order(price=1, volume=1)
'''

Order = namedtuple('order', 'id price volume')

In [5]:
class dynamic_order:
    '''
    extension of Order, used in making deals
    '''
    def __init__(self, order):
        assert isinstance(order, Order)
        self.id = order.id
        self.price = order.price
        self.volume = order.volume
    @property
    def show(self):
        print('id : %d' % self.id)
        print('price : %d' % self.price)
        print('volume : %d' % self.volume)

In [75]:
class Trader:
    '''
    A primary class to define an investor
    '''
    def __init__(self, id):
        self.id = id
        self.cash = 0 # 现金
        self.cash_history = []
        self.asset = 0 # 总资产
        self.asset_history = []
        self.stock = 0 # 持股
        self.stock_history = []
        self.trade_history = [] # 交易记录
        self.price = 0
        self.order = Order(id=self.id,
                           price=0,
                           volume=0)
        
    def gen_order(self):
        self.order = Order(id=self.id,
                           price=np.random.randint(-10, 10), 
                           volume=np.random.randint(1, 5))
        
    def update(self, price, vol):
        vol *= np.sign(self.order.price)
        price = abs(price)
        self.cash -= price * vol
        self.cash_history.append(self.cash)
        self.stock += vol
        self.stock_history.append(self.stock)
        self.trade_history.append((price, vol))
        self.price = price
        self.asset = self.cash + self.stock * self.price
        self.asset_history.append(self.asset)
        
    @property
    def show(self):
        print('id : %d, cash : %d, stock : %d, stock_price : %d, asset : %d' % 
             (self.id, self.cash, self.stock, self.price, self.asset))
        
#         print('asset : %d' % self.asset)
#         print('stock : %d' % self.stock)

In [92]:
def make_deals(orders):
    buy_list = [dynamic_order(order) for order in orders if order.price>0]
    sell_list = [dynamic_order(order) for order in orders if order.price<0]

    buy_list = sorted(buy_list, key=lambda x:(-x.price, x.id))
    sell_list = sorted(sell_list, key=lambda x:(abs(x.price), x.id))
    deal_result = np.zeros(len(orders), int)
    price = 0
    if len(buy_list)==0 or len(sell_list)==0:
        return price, deal_result
    while sell_list[0].price+buy_list[0].price>=0:
        if sell_list[0].volume>=buy_list[0].volume:
            sell_list[0].volume -= buy_list[0].volume
            deal_result[buy_list[0].id] += buy_list[0].volume
            deal_result[sell_list[0].id] += buy_list[0].volume
            if sell_list[0].volume==buy_list[0].volume:
                price = (buy_list[0].price + abs(sell_list[0].price)) / 2
            else:
                price = abs(sell_list[0].price)
            _ = buy_list.pop(0)
        else:
            buy_list[0].volume -= sell_list[0].volume
            deal_result[buy_list[0].id] += sell_list[0].volume
            deal_result[sell_list[0].id] += sell_list[0].volume
            price = buy_list[0].price
            _ = sell_list.pop(0)           
        price = abs(price)
        if len(buy_list)==0 or len(sell_list)==0:
            break
    return price, deal_result

In [93]:
investors = [Trader(i) for i in range(200)]

In [94]:
start = time.time()
for step in range(3000):
    orders = []
    for investor in investors:
        investor.gen_order()
        orders.append(investor.order)

    price, deal_result = make_deals(orders)
    for i,investor in enumerate(investors):
        investor.update(price=price, vol=deal_result[i])
        
print('用时:', time.time()-start)


用时: 11.734297037124634

In [91]:
len(orders)


Out[91]:
200

In [79]:
for investor in investors:
    investor.show


id : 0, cash : -270, stock : 41, stock_price : 4, asset : -106
id : 1, cash : 378, stock : -58, stock_price : 4, asset : 146
id : 2, cash : 445, stock : -105, stock_price : 4, asset : 25
id : 3, cash : 473, stock : -112, stock_price : 4, asset : 25
id : 4, cash : -407, stock : 81, stock_price : 4, asset : -83
id : 5, cash : 195, stock : -29, stock_price : 4, asset : 79
id : 6, cash : -271, stock : 65, stock_price : 4, asset : -11
id : 7, cash : -95, stock : 1, stock_price : 4, asset : -91
id : 8, cash : -7, stock : 12, stock_price : 4, asset : 41
id : 9, cash : -92, stock : 10, stock_price : 4, asset : -52
id : 10, cash : 42, stock : -8, stock_price : 4, asset : 10
id : 11, cash : 218, stock : -31, stock_price : 4, asset : 94
id : 12, cash : -20, stock : -8, stock_price : 4, asset : -52
id : 13, cash : -74, stock : 10, stock_price : 4, asset : -34
id : 14, cash : -374, stock : 68, stock_price : 4, asset : -102
id : 15, cash : -260, stock : 49, stock_price : 4, asset : -64
id : 16, cash : -30, stock : 20, stock_price : 4, asset : 49
id : 17, cash : 419, stock : -51, stock_price : 4, asset : 215
id : 18, cash : -322, stock : 53, stock_price : 4, asset : -110
id : 19, cash : 53, stock : -8, stock_price : 4, asset : 21

In [80]:
import time
a = time.time()

In [82]:
b = time.time()-a
print(b)


14.392970323562622