Time for action – avoiding loops with vectorize()

The vectorize() function is a yet another trick to reduce the number of loops in your programs. Calculate the profit of a single trading day following these steps:

  1. First, load the data:
    o, h, l, c = np.loadtxt('BHP.csv', delimiter=',', usecols=(3, 4, 5, 6), unpack=True)
  2. The vectorize() function is the NumPy equivalent of the Python map() function. Call the vectorize() function, giving it as an argument the calc_profit() function:
    func = np.vectorize(calc_profit)
  3. We can now apply func() as if it is a function. Apply the func() function result that we got to the price arrays:
    profits = func(o, h, l, c)
  4. The calc_profit() function is pretty simple. First, we try to buy slightly below the open price. If this is outside of the daily range, then, obviously, our attempt failed and no profit was made, or we incurred a loss, therefore, will return 0. Otherwise, we sell at the close price and the profit is simply the difference between the buy price and the close price. Actually, it is, in fact, more interesting to have a look at the relative profit:
    def calc_profit(open, high, low, close):
       #buy just below the open
       buy = open * 0.999
       # daily range
       if low <  buy < high:
          return (close - buy)/buy
       else:
          return 0
    
    print("Profits", profits)
  5. Assume that there are two days with zero profits, where there was either no net gain or a loss. Select the days with trades and calculate the averages:
    real_trades = profits[profits != 0]
    print("Number of trades", len(real_trades), round(100.0 * len(real_trades)/len(c), 2), "%")
    print("Average profit/loss %", round(np.mean(real_trades) * 100, 2))

    The trades summary is shown as follows:

    Number of trades 28 93.33 %
    Average profit/loss % 0.02
    
  6. As optimists, we are interested in winning trades with a gain greater than zero. Select the days with winning trades and calculate the averages:
    winning_trades = profits[profits > 0]
    print("Number of winning trades", len(winning_trades), round(100.0 * len(winning_trades)/len(c), 2), "%")
    print("Average profit %", round(np.mean(winning_trades) * 100, 2))

    The winning trades statistics are as follows:

    Number of winning trades 16 53.33 %
    Average profit % 0.72
    
  7. Alternatively, as pessimists, we are interested in losing trades with a profit less than zero. Select the days with losing trades and calculate the averages:
    losing_trades = profits[profits < 0]
    print("Number of losing trades", len(losing_trades), round(100.0 * len(losing_trades)/len(c), 2), "%")
    print("Average loss %", round(np.mean(losing_trades) * 100, 2))

    The losing trades statistics are as follows:

    Number of losing trades 12 40.0 %
    Average loss % -0.92
    

What just happened?

We vectorized a function, which is just another way to avoid using loops. We simulated a trading day with a function, which returned the relative profit of each day's trade. We printed a statistics summary of the losing and winning trades (see simulation.py):

from __future__ import print_function
import numpy as np

o, h, l, c = np.loadtxt('BHP.csv', delimiter=',', usecols=(3, 4, 5, 6), unpack=True)

def calc_profit(open, high, low, close):
   #buy just below the open
   buy = open * 0.999

   # daily range
   if low <  buy < high:
      return (close - buy)/buy
   else:
      return 0

func = np.vectorize(calc_profit)
profits = func(o, h, l, c)
print("Profits", profits)

real_trades = profits[profits != 0]
print("Number of trades", len(real_trades), round(100.0 * len(real_trades)/len(c), 2), "%")
print("Average profit/loss %", round(np.mean(real_trades) * 100, 2))

winning_trades = profits[profits > 0]
print("Number of winning trades", len(winning_trades), round(100.0 * len(winning_trades)/len(c), 2), "%")
print("Average profit %", round(np.mean(winning_trades) * 100, 2))

losing_trades = profits[profits < 0]
print("Number of losing trades", len(losing_trades), round(100.0 * len(losing_trades)/len(c), 2), "%")
print("Average loss %", round(np.mean(losing_trades) * 100, 2))

Have a go hero – analyzing consecutive wins and losses

Although the average profit is positive, it is also important to know whether we had to endure a long streak of consecutive losses. If this is the case, we might be left with little or no capital, and then the average profit would not matter.

Find out if there was such a losing streak. If you want, you can also find out if there was a prolonged winning streak.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset