Welcome, guest | Sign In | My Account | Store | Cart
from collections import deque

import random

'''
    Example below replicates 
    
    +75 MSFT 25.10
    +50 MSFT 25.12
    -100 MSFT 25.22
    
    Realized P&L = 75 * (25.22 - 25.10) + 25 * (25.22 - 25.12) = $ 11.50
    
    A Trade is split into a set of unit positions that are then dequeued on FIFO basis as part of Sell.

'''

number_of_sell_trades = 1000
max_sell_quentity = 5
min_sell_price = 23.00
max_sell_price = 27.00

class TradeManager():        

    def __init__(self):
        # FIFO queue that we can use to enqueue unit buys and
        # dequeue unit sells.
        self.fifo = deque()
        self.profit = []

    def __repr__(self):
        return 'position size: %d'%(len(self.fifo))
        
    def execute_with_total_pnl(self, direction, quantity, price):            
        #print direction, quantity, price, 'position size', len(self.fifo)
        
        if len(self.fifo) == 0:
            return 0
        
        if 'Sell' in (direction):            
            if len(self.fifo) >= quantity:                
                return sum([(price - fill.price) for fill in tm.execute(direction, quantity, price)])                
            else:
                return 0                
        else:
            return [tm.execute(direction, quantity, price)]           
            
    def execute(self, direction, quantity, price):        
        #print direction, quantity, price, 'position size', len(self.fifo)
        if direction in ('Buy'):            
            for i, fill in Trade(direction, quantity, price):                
                self.fifo.appendleft(fill)            
                yield fill
        elif direction in ('Sell'):
            for i, fill in Trade(direction, quantity, price):                
                yield self.fifo.pop()        

class Fill():    
        def __init__(self, price):
            self.price = price
            self.quantity = 1

class Trade():            
    def __init__(self, direction, quantity, price):
        self.direction = direction
        self.quantity = quantity
        self.price = price
        self.i = 0 
        
    def __iter__(self):
        return self
    
    def next(self):
        if self.i < self.quantity:
            i = self.i
            self.i += 1
            return i, Fill(self.price)
        else:
            raise StopIteration()
            
# create a TradeManager
tm = TradeManager()

# generate some buys
a = [i for i in tm.execute('Buy', 75, 25.10)]    
a = [i for i in tm.execute('Buy', 50, 25.12)]  

# generate sell
pnl = np.cumsum(tm.execute_with_total_pnl('Sell', 100, 25.22))

# how much did we make
print 'total pnl', pnl[-1:]

# try something more involved.
tm = TradeManager()
pnl_ending = []

# run n simulations 
for step in range(0,50):
    a = [i for i in tm.execute('Buy', 75000, 25)]    
    pnl = np.cumsum([tm.execute_with_total_pnl('Sell', quantity, random.uniform(min_sell_price, max_sell_price)) \
                 for quantity in [random.randint(0,max_sell_quentity) \
                                  for i in range(0,number_of_sell_trades,1)]])
    plot(pnl)
    pnl_ending.append(pnl[-1:][0])
    print 'step', step, 'pnl', pnl[-1:][0], 'avg. pnl', np.mean(pnl_ending), 'diff to mean', pnl[-1:][0]-np.mean(pnl_ending)
    
print 'avg, total pnl', np.mean(pnl_ending) #pnl[-1:][0]
show()

# bin the results
hist(pnl_ending, 25)
grid(True)
show()

# could lookat fitting and var.

Diff to Previous Revision

--- revision 1 2015-02-10 12:46:10
+++ revision 2 2015-02-10 13:34:48
@@ -15,14 +15,16 @@
 
 '''
 
-number_of_sell_trades = 100
+number_of_sell_trades = 1000
 max_sell_quentity = 5
 min_sell_price = 23.00
-max_sell_price = 25.00
+max_sell_price = 27.00
 
-class TradeManager():
+class TradeManager():        
 
     def __init__(self):
+        # FIFO queue that we can use to enqueue unit buys and
+        # dequeue unit sells.
         self.fifo = deque()
         self.profit = []
 
@@ -30,48 +32,35 @@
         return 'position size: %d'%(len(self.fifo))
         
     def execute_with_total_pnl(self, direction, quantity, price):            
-        print direction, quantity, price, 'position size', len(self.fifo)
+        #print direction, quantity, price, 'position size', len(self.fifo)
         
         if len(self.fifo) == 0:
             return 0
         
         if 'Sell' in (direction):            
             if len(self.fifo) >= quantity:                
-                return sum([(fill.price - price) for fill in tm.execute(direction, quantity, price)])                
+                return sum([(price - fill.price) for fill in tm.execute(direction, quantity, price)])                
             else:
-                return 0
-                #raise MyShortSellException('No short selling allowed')
+                return 0                
         else:
-            return [tm.execute(direction, quantity, price)]
-    
-    #def execute_with_pnl(self, direction, quantity, price):    
-    #    if 'Sell' in (direction):
-    #       for fill in tm.execute(direction, quantity, price):
-    #            self.profit.append(fill.price - price)
-    #            yield (fill.price - price)
-    #    else:
-    #        yield tm.execute(direction, quantity, price)            
+            return [tm.execute(direction, quantity, price)]           
             
-    def execute(self, direction, quantity, price, verbose=False):
-        if verbose:
-            print 'before', (self.fifo)
-        if direction in ('Buy'):
-            #print 'Buy'
+    def execute(self, direction, quantity, price):        
+        #print direction, quantity, price, 'position size', len(self.fifo)
+        if direction in ('Buy'):            
             for i, fill in Trade(direction, quantity, price):                
                 self.fifo.appendleft(fill)            
                 yield fill
         elif direction in ('Sell'):
             for i, fill in Trade(direction, quantity, price):                
-                yield self.fifo.pop()
-        if verbose: 
-            print 'after', len(self.fifo)
+                yield self.fifo.pop()        
 
-class Fill():
+class Fill():    
         def __init__(self, price):
             self.price = price
             self.quantity = 1
 
-class Trade():        
+class Trade():            
     def __init__(self, direction, quantity, price):
         self.direction = direction
         self.quantity = quantity
@@ -93,22 +82,35 @@
 tm = TradeManager()
 
 # generate some buys
-a = [i for i in tm.execute('Buy', 75, 25.12)]    
-a = [i for i in tm.execute('Buy', 50, 25.22)]  
+a = [i for i in tm.execute('Buy', 75, 25.10)]    
+a = [i for i in tm.execute('Buy', 50, 25.12)]  
 
-# generate some sells
-pnl = np.cumsum([tm.execute_with_total_pnl('Sell', quantity, random.uniform(min_sell_price, max_sell_price)) \
-                 for quantity in [random.randint(0,max_sell_quentity) \
-                                  for i in range(0,number_of_sell_trades,1)]])
-plot(pnl)
+# generate sell
+pnl = np.cumsum(tm.execute_with_total_pnl('Sell', 100, 25.22))
+
+# how much did we make
 print 'total pnl', pnl[-1:]
-
 
 # try something more involved.
 tm = TradeManager()
-a = [i for i in tm.execute('Buy', 75, 25.10)]    
-pnl = np.cumsum([tm.execute_with_total_pnl('Sell', quantity, random.uniform(min_sell_price, max_sell_price)) \
+pnl_ending = []
+
+# run n simulations 
+for step in range(0,50):
+    a = [i for i in tm.execute('Buy', 75000, 25)]    
+    pnl = np.cumsum([tm.execute_with_total_pnl('Sell', quantity, random.uniform(min_sell_price, max_sell_price)) \
                  for quantity in [random.randint(0,max_sell_quentity) \
                                   for i in range(0,number_of_sell_trades,1)]])
-plot(pnl)
-print 'total pnl', pnl[-1:]
+    plot(pnl)
+    pnl_ending.append(pnl[-1:][0])
+    print 'step', step, 'pnl', pnl[-1:][0], 'avg. pnl', np.mean(pnl_ending), 'diff to mean', pnl[-1:][0]-np.mean(pnl_ending)
+    
+print 'avg, total pnl', np.mean(pnl_ending) #pnl[-1:][0]
+show()
+
+# bin the results
+hist(pnl_ending, 25)
+grid(True)
+show()
+
+# could lookat fitting and var.

History