title: How to maximize revenue - Python
body: <p>I have a large df consisting of hourly share prices. I was hoping to find the optimal buy price and sell price to maximize earnings (revenue - costs). I have no idea what the maximizing buy/sell prices would be, therefore my initial guess is a wild stab in the dark.</p>
  
  <p>I tried to use Scipy 'minimize' and 'basin hopping'. When I run the script, I appear to be getting stuck in local wells, with the results barely moving away from my initial guess. </p>
  
  <p>Any ideas on how I can resolve this? is there a better way to write the code, or a better method to use. </p>
  
  <p>Sample code below</p>
  
  <pre><code>import pandas as pd
  import numpy as np
  import scipy.optimize as optimize
  
  df = pd.DataFrame({
      'Time': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
      'Price': [44, 100, 40, 110, 77, 109, 65, 93, 89, 49]})
  
  # Create Empty Columns
  df[['Qty', 'Buy', 'Sell', 'Cost', 'Rev']] = pd.DataFrame([[0.00, 0.00, 0.00, 0.00, 0.00]], index=df.index)
  
  
  # Create Predicate to add fields
  class Predicate:
      def __init__(self):
          self.prev_time = -1
          self.prev_qty = 0
          self.prev_buy = 0
          self.prev_sell = 0
          self.Qty = 0
          self.Buy = 0
          self.Sell = 0
          self.Cost = 0
          self.Rev = 0
  
      def __call__(self, x):
          if x.Time == self.prev_time:
              x.Qty = self.prev_qty
              x.Buy = self.prev_buy
              x.Sell = self.prev_sell
              x.Cost = x.Buy * x.Price
              x.Rev = x.Sell * x.Price
          else:
              x.Qty = self.prev_qty + self.prev_buy - self.prev_sell
              x.Buy = np.where(x.Price &lt; buy_price, min(30 - x.Qty, 10), 0)
              x.Sell = np.where(x.Price &gt; sell_price, min(x.Qty, 10), 0)
              x.Cost = x.Buy * x.Price
              x.Rev = x.Sell * x.Price
              self.prev_buy = x.Buy
              self.prev_qty = x.Qty
              self.prev_sell = x.Sell
              self.prev_time = x.Time
          return x
  
  
  # Define function to minimize
  def max_rev(params):
      global buy_price
      global sell_price
      buy_price, sell_price = params
      df2 = df.apply(Predicate(), axis=1)
      return -1 * (df2['Rev'].sum() - df2['Cost'].sum())
  
  
  # Run optimization
  initial_guess = [40, 90]
  result = optimize.minimize(fun=max_rev, x0=initial_guess, method='BFGS')
  # result = optimize.basinhopping(func=max_rev, x0=initial_guess, niter=1000, stepsize=10)
  print(result.x)
  
  # Run the final results
  result.x = buy_price, sell_price
  df = df.apply(Predicate(), axis=1)
  print(df)
  print(df['Rev'].sum() - df['Cost'].sum())
  </code></pre>