Ejemplo n.º 1
0
    def runBacktest(self, path, longWindow, shortWindow, display):
        dataframe = pd.read_csv(path)
        count = len(dataframe)

        for i in range(1, count):

            heuristicResult = self.heuristic(dataframe, longWindow, shortWindow, i)
            lastPrice = dataframe.iloc[i]["close"]
            date = dataframe.iloc[i]["timestamp"]

            if heuristicResult == 1 and not self.isLong():

                """ Executing ORDINARY BUY order """
                self.balance, self.unitsAvailable, self.stopLoss, self.takeProfit = tradeUtil.ordinaryBuyMax(dataframe.iloc[i]["timestamp"], self.balance, dataframe.iloc[i]["close"], self.unitsAvailable, display)
                self.lastBuyIndex = i
                self.buyDates.append(pd.to_datetime(date))

            elif self.isLong() and (lastPrice < self.stopLoss or lastPrice > self.takeProfit):
                if lastPrice < self.stopLoss:

                    """ Executing STOP LOSS SELL order """
                    self.balance, self.unitsAvailable = tradeUtil.stopLossSell(dataframe.iloc[i]["timestamp"], self.balance, self.stopLoss, self.unitsAvailable, display)
                    diff1 = dataframe.iloc[i-1]["close"] - dataframe.iloc[i]["close"]
                    diff2 = dataframe.iloc[i-1]["close"] - self.stopLoss
                    frac = (diff2/diff1)*24
                    self.sellDates.append(pd.to_datetime(date)-timedelta(hours=24-frac))

                elif lastPrice > self.takeProfit:

                    """ Executing TAKE PROFIT SELL order """
                    self.balance, self.unitsAvailable = tradeUtil.takeProfitSell(dataframe.iloc[i]["timestamp"], self.balance, dataframe.iloc[i]["close"], self.unitsAvailable, display)
                    self.sellDates.append(pd.to_datetime(date))

                """ Transferring excess funds from balance to savings """
                if self.balance > self.startingBalance:
                    self.saved += self.balance - self.startingBalance
                    self.balance = self.startingBalance

        """ If last BUY order has no corresponding SELL order, do not include it in profit/loss calculations. """
        if self.isLong():
            if display:
                print("NOTE: Last BUY entry printed above was not closed, and is not factored in Profit/Loss calculation.")
            self.buyDates = self.buyDates[:-1]
            self.balance += dataframe.iloc[self.lastBuyIndex]["close"] * self.unitsAvailable

        self.balance = self.balance + self.saved
        returnPercentage = 100*((self.balance-self.startingBalance)/self.startingBalance)
        period = util.periods(path)/365

        avgReturnPercentage = round(returnPercentage/period, 2)
        period = round(period, 2)
        returnPercentage = round(returnPercentage, 2)
        self.balance = round(self.balance, 2)

        print("\nReturn: " + str(returnPercentage) + "% over a period of " + str(period) + " years (" + str(avgReturnPercentage) + "% per annum)")
        sys.stdout.flush()
        return self.buyDates, self.sellDates
Ejemplo n.º 2
0
def smaCrossover(path, window):
    smaColumn = "sma" + str(window)
    dataframe = pd.read_csv(path)
    count = len(dataframe)

    startingBalance = 1000000
    balance = startingBalance
    unitsAvailable = 0
    long = False

    for i in range(0, count):
        if (dataframe.iloc[i]["close"] >
                dataframe.iloc[i][smaColumn]) and (not long):
            qty = math.floor(balance / dataframe.iloc[i]["close"])
            print(
                str(dataframe.iloc[i]["timestamp"]) + ": BUY " + str(qty) +
                " units at $" + str(dataframe.iloc[i]["close"]))
            long = True
            balance -= dataframe.iloc[i]["close"] * qty
            unitsAvailable += qty
        elif (dataframe.iloc[i]["close"] <
              dataframe.iloc[i][smaColumn]) and (long):
            print(
                str(dataframe.iloc[i]["timestamp"]) + ": SELL " +
                str(unitsAvailable) + " at $" +
                str(dataframe.iloc[i]["close"]))
            long = False
            balance += dataframe.iloc[i]["close"] * unitsAvailable
            unitsAvailable = 0
    if unitsAvailable > 0:
        balance += dataframe.iloc[0]["close"] * unitsAvailable

    returnPercentage = 100 * ((balance - startingBalance) / startingBalance)
    period = util.periods(dataframe) / 365

    avgReturnPercentage = round(returnPercentage / period, 2)
    period = round(period, 2)
    returnPercentage = round(returnPercentage, 2)
    balance = round(balance, 2)

    print("\nBalance: " + str(balance) + "\nReturn Percentage: " +
          str(returnPercentage) + "% over a period of " + str(period) +
          " years.")
    print("Average Yearly Return Percentage: " + str(avgReturnPercentage) +
          "%")
    print("Buy and Hold Return Percentage would have been: " + str(
        round(
            100 *
            (dataframe.iloc[count - 1]['close'] - dataframe.iloc[0]['close']) /
            dataframe.iloc[0]['close'], 2)) + "%")
    print("I.e. Bought at $" + str(dataframe.iloc[0]['close']) + " on " +
          str(dataframe.iloc[0]['timestamp'] + " and sold at $" +
              str(dataframe.iloc[count - 1]['close']) + " on " +
              str(dataframe.iloc[count - 1]['timestamp'])))

    print("--------------------")
    sys.stdout.flush()
Ejemplo n.º 3
0
    def runBacktest(self, path, window):
        dataframe = pd.read_csv(path)
        count = len(dataframe)

        for i in range(0, count):
            heuristicResult = self.heuristic(dataframe, window, i)

            if heuristicResult == 1 and not self.isLong():
                self.balance, self.unitsAvailable, self.stopLoss = tradeUtil.ordinaryBuyMax(
                    dataframe.iloc[i]["timestamp"], self.balance,
                    dataframe.iloc[i]["close"], self.unitsAvailable)
                self.lastBuyIndex = i

            elif heuristicResult == 0 and self.isLong():
                self.balance, self.unitsAvailable = tradeUtil.ordinarySellMax(
                    dataframe.iloc[i]["timestamp"], self.balance,
                    dataframe.iloc[i]["close"], self.unitsAvailable)

        # Make sure last buy was closed --- fix this
        if self.isLong():
            print(
                "NOTE: Last BUY entry printed above is invalid. Please ignore."
            )
            self.balance += dataframe.iloc[
                self.lastBuyIndex]["close"] * self.unitsAvailable

        returnPercentage = 100 * (
            (self.balance - self.startingBalance) / self.startingBalance)
        period = util.periods(dataframe) / 365

        avgReturnPercentage = round(returnPercentage / period, 2)
        period = round(period, 2)
        returnPercentage = round(returnPercentage, 2)
        self.balance = round(self.balance, 2)

        print("\nReturn: " + str(returnPercentage) + "% over a period of " +
              str(period) + " years (" + str(avgReturnPercentage) +
              "% per annum)")
        print("--------------------")
        sys.stdout.flush()
Ejemplo n.º 4
0
if forcePull and os.path.isfile(rawPath):
    os.unlink(rawPath)

if os.path.isfile(enrichedPath):
    os.unlink(enrichedPath)

""" Pull and/or Enrich pricing data """
pullAndEnrich.pullAndEnrich(ticker, "full", rawPath, enrichedPath, indicators)


""" Backtest Random strategy """
util.printPartition()
print("Simulating Random Strategy " + str(randomStrategyCount) + " times.")
randomReturn = randomStrategy.runMultipleRandoms(enrichedPath, randomStrategyCount)
print("\nRandom strategy would have returned: " + str(randomReturn) + "% over a period of " + str(round(util.periods(enrichedPath)/365, 2)) + " years (on average).")
sys.stdout.flush()


""" Backtest each strategy requested """
for strategy in strategies:

    if "smac" in strategy:
        horizon = strategy[4:]
        util.printPartition()
        print("Simulating SMA Crossover Strategy with time horizon: " + horizon)
        sys.stdout.flush()
        buys, sells = SMACrossover.SMACrossover().runBacktest(enrichedPath, int(horizon), display)
        if plotBacktests:
            simplePlt.plot(ticker, enrichedPath, buys, sells, "SMA Crossover (" + horizon + " day) Strategy Backtest")
Ejemplo n.º 5
0
def smaLongShortCrossover(path, longWindow, shortWindow):
    longSMAColumn = "sma" + str(longWindow)
    shortSMAColumn = "sma" + str(shortWindow)
    dataframe = pd.read_csv(path)
    count = len(dataframe)

    print("--------------------")
    print("Running SMA " + str(longWindow) + "/" + str(shortWindow) +
          " Long/Short Crossover Strategy.")
    print("--------------------")

    startingBalance = 1000000
    balance = startingBalance
    unitsAvailable = 0
    long = False
    lastPrice = 0
    stoploss = -1
    entry = -1
    stoplossPCT = .25
    for i in range(1, count):

        if long and dataframe.iloc[i]['close'] <= stoploss:
            qty = math.floor(unitsAvailable * stoplossPCT)
            print(
                str(dataframe.iloc[i]["timestamp"]) +
                ": **PARTIAL STOP LOSS SELL** " + str(qty) + " at $" +
                str(dataframe.iloc[i]['close']))
            sys.stdout.flush()
            balance += dataframe.iloc[i]['close'] * qty
            unitsAvailable -= qty
            if unitsAvailable == 0:
                long = False
            stoploss = stoploss - 0.05 * stoploss
            continue
        """
        if long and dataframe.iloc[i]['close'] >= 1.1*entry:
            print (str(dataframe.iloc[i]["timestamp"]) + ": **PROFIT SELL** " + str(unitsAvailable) + " at $" + str(dataframe.iloc[i]['close']))
            sys.stdout.flush()
            long = False
            balance += dataframe.iloc[i]['close'] * unitsAvailable
            unitsAvailable = 0
            continue
        """
        if (dataframe.iloc[i][shortSMAColumn] >
                dataframe.iloc[i][longSMAColumn]) and (
                    not long) and (dataframe.iloc[i - 1][shortSMAColumn] <
                                   dataframe.iloc[i - 1][longSMAColumn]):
            qty = math.floor(balance / dataframe.iloc[i]["close"])
            print(
                str(dataframe.iloc[i]["timestamp"]) + ": **BUY** " + str(qty) +
                " units at $" + str(dataframe.iloc[i]["close"]))
            sys.stdout.flush()
            long = True
            stoploss = dataframe.iloc[i][
                "close"] - 0.05 * dataframe.iloc[i]["close"]
            entry = dataframe.iloc[i]["close"]
            #print("Setting STOP LOSS at " + str(stoploss))
            sys.stdout.flush()
            balance -= dataframe.iloc[i]["close"] * qty
            unitsAvailable += qty
            lastPrice = dataframe.iloc[i]["close"]
        elif (dataframe.iloc[i][shortSMAColumn] <
              dataframe.iloc[i][longSMAColumn]) and (
                  long) and (dataframe.iloc[i - 1][shortSMAColumn] >
                             dataframe.iloc[i - 1][longSMAColumn]
                             ):  # and dataframe.iloc[i]["close"] > lastPrice:
            print(
                str(dataframe.iloc[i]["timestamp"]) + ": **SELL** " +
                str(unitsAvailable) + " at $" +
                str(dataframe.iloc[i]["close"]))
            sys.stdout.flush()
            long = False
            balance += dataframe.iloc[i]["close"] * unitsAvailable
            unitsAvailable = 0
    if unitsAvailable > 0:
        balance += dataframe.iloc[i]["close"] * unitsAvailable
        print(
            str(dataframe.iloc[i]["timestamp"]) + ": **FORCE SELL** " +
            str(unitsAvailable) + " at $" + str(dataframe.iloc[i]["close"]))

    returnPercentage = 100 * ((balance - startingBalance) / startingBalance)
    period = util.periods(dataframe) / 365

    avgReturnPercentage = round(returnPercentage / period, 2)
    period = round(period, 2)
    returnPercentage = round(returnPercentage, 2)
    balance = round(balance, 2)

    print("\nBalance: " + str(balance) + "\nReturn Percentage: " +
          str(returnPercentage) + "% over a period of " + str(period) +
          " years.")
    #print("Average Yearly Return Percentage: " + str(avgReturnPercentage) + "%")

    print("Buy and Hold Return Percentage would have been: " + str(
        round(
            100 *
            (dataframe.iloc[count - 1]['close'] - dataframe.iloc[0]['close']) /
            dataframe.iloc[0]['close'], 2)) + "%")
    print("I.e. Bought at $" + str(dataframe.iloc[0]['close']) + " on " +
          str(dataframe.iloc[0]['timestamp'] + " and sold at $" +
              str(dataframe.iloc[count - 1]['close']) + " on " +
              str(dataframe.iloc[count - 1]['timestamp'])))
    print("--------------------\n\n")
    sys.stdout.flush()