Beispiel #1
0
 def runMod(mod, joinedData):
     pred = dataAck.computePosition([
         mod.makeTodayPrediction(
             portfolio.prepareDataForModel(mod, joinedData))
     ])
     print(mod.describe(), pred, joinedData.index[-1])
     portfolio.storeModelPrediction(mod, pred, joinedData.index[-1])
     ##ENSURE POPULATED FOR CORRECT PREDICTION STYLE
     i = mod.inputSeries.predictionPeriod - 1
     while i > 0:
         pred = dataAck.computePosition(
             [mod.makeTodayPrediction(joinedData[:-i])])
         print(mod.describe(), pred, joinedData[:-i].index[-1])
         portfolio.storeModelPrediction(mod, pred,
                                        joinedData[:-i].index[-1])
         i -= 1
def runBackfillMP(mod, joinedData, threadsToUse, backfillDays = 30):
    mpEngine = mp.get_context('fork')
    i = mod.inputSeries.predictionPeriod - 1 + backfillDays
    runningP = []
    while i > 0:
        while len(runningP) > threadsToUse:
            runningP = dataAck.cycleP(runningP)
        
        p = mpEngine.Process(target=runModPredictionBackfill, args=(mod, joinedData[:-i], backfillDays, ))
        p.start()
        runningP.append(p)
        i -= 1
    
    while len(runningP) > 0:
        runningP = dataAck.cycleP(runningP)
    
    print("CHECKING AGGREGATE PREDICTIONS")
    ##STORE AGGREGATE PREDICTIONS
    i = mod.inputSeries.predictionPeriod - 1 + backfillDays
    allPreds = portfolio.getPredictionsByModel(mod)
    while i > 0:
        lastDay = joinedData[:-i].index[-1]
        todayPredictions = []
        for pred in allPreds:
            ##CHECK IF PREDICTION STILL VALID
            if len(joinedData[str(pred["lastDataDayUsed"]):lastDay]) - 1 < pred["predictionLength"] and len(joinedData[str(pred["lastDataDayUsed"]):lastDay]) > 0:##GETS TRADING DAYS SINCE LAST DATA DAY
                todayPredictions.append(pred["prediction"])
       
        ##SKIP UPLOAD IF NOT ENOUGH PREDICTIONS
        print(lastDay, len(todayPredictions))
        if len(todayPredictions) == mod.inputSeries.predictionPeriod:
            pred = dataAck.computePosition(todayPredictions)
            print(mod.describe(), todayPredictions, pred)
            portfolio.storeAggregateModelPrediction(mod, pred, lastDay)
        i -= 1
Beispiel #3
0
def getAggregatePredictionForModelDaily(model, joinedData):
    todayPredictions = []
    for pred in getPredictionsByModel(model):
        ##CHECK IF PREDICTION STILL VALID
        if len(joinedData[str(pred["lastDataDayUsed"]):]) - 1 < pred[
                "predictionLength"]:  ##GETS TRADING DAYS SINCE LAST DATA DAY
            todayPredictions.append(pred["prediction"])
    #print(model.describe(), todayPredictions, dataAck.computePosition(todayPredictions))
    return dataAck.computePosition(todayPredictions)
Beispiel #4
0
def generateRawPredictions(allModels, joinedData, daysBack=False):
    for mod in allModels:
        pred = dataAck.computePosition([
            mod.makeTodayPrediction(
                portfolio.prepareDataForModel(mod, joinedData))
        ])
        print(mod.describe(), pred, joinedData.index[-1])
        portfolio.storeModelPrediction(mod, pred, joinedData.index[-1])
        if daysBack == True:
            ##ENSURE POPULATED FOR CORRECT PREDICTION STYLE
            i = mod.inputSeries.predictionPeriod - 1
            while i > 0:
                pred = dataAck.computePosition(
                    [mod.makeTodayPrediction(joinedData[:-i])])
                print(mod.describe(), pred, joinedData[:-i].index[-1])
                portfolio.storeModelPrediction(mod, pred,
                                               joinedData[:-i].index[-1])
                i -= 1
 def runModelToday(self, dataOfInterest):
     xVals, yVals, yIndex, xToday = self.generateWindows(dataOfInterest)
     ##GET PERTINENT PREDICTIONS
     i = 0
     predictionsToJoin = []
     while i < self.predictionDistance:
         xTarget = xVals[-i]
         thisDayPrediction = self.runDay(xVals[:-i - 1], yVals[:-i - 1], xTarget, identifier=None, sharedDict=None)
         predictionsToJoin.append(thisDayPrediction)
         i += 1
     print("PREDICTIONS TO JOIN", predictionsToJoin)
     return dataAck.computePosition(predictionsToJoin)
     
def runModPredictionBackfill(mod, dataToUse, backfillDays = 30):
    ##ENSURE POPULATED FOR CORRECT PREDICTION STYLE
    pred = dataAck.computePosition([mod.makeTodayPrediction(dataToUse)])
    print(mod.describe(), pred, dataToUse.index[-1])
    portfolio.storeModelPrediction(mod, pred, dataToUse.index[-1])
Beispiel #7
0
 def runModelToday(self, dataOfInterest):
     return self.combinePredictions([
         dataAck.computePosition([self.obj1.runModelToday(dataOfInterest)]),
         dataAck.computePosition([self.obj2.runModelToday(dataOfInterest)])
     ])
Beispiel #8
0
    def runModelHistorical(self, dataOfInterest):

        ##RAW PREDICTIONS ARE PREDS 0->1.0
        returnStream, factorReturn, predictions, slippageAdjustedReturn, rawPredictions1 = self.obj1.runModelHistorical(
            dataOfInterest)
        returnStream, factorReturn, predictions, slippageAdjustedReturn, rawPredictions2 = self.obj2.runModelHistorical(
            dataOfInterest)

        print(rawPredictions1)
        print(rawPredictions2)
        #computePositionConfidence
        rawPredictions1 = pd.DataFrame(rawPredictions1.apply(
            lambda x: dataAck.computePosition(x), axis=1),
                                       columns=["Predictions 1"]).dropna()
        rawPredictions2 = pd.DataFrame(rawPredictions2.apply(
            lambda x: dataAck.computePosition(x), axis=1),
                                       columns=["Predictions 2"]).dropna()

        print(rawPredictions1)
        print(rawPredictions2)

        rawPredictions = rawPredictions1.join(rawPredictions2).dropna()

        print(rawPredictions)
        #averagePredictions
        predsTable = pd.DataFrame(
            rawPredictions.apply(lambda x: self.combinePredictions(x),
                                 axis=1,
                                 raw=True))
        rawPredictions = predsTable
        ##PREDICTIONS COMBINED AS 0, 0.5, 1 where

        i = 1
        tablesToJoin = []
        while i < self.predictionDistance:
            thisTable = predsTable.shift(i)
            thisTable.columns = ["Predictions_" + str(i)]
            tablesToJoin.append(thisTable)
            i += 1

        returnStream = None
        factorReturn = None
        predictions = None
        slippageAdjustedReturn = None

        predsTable = predsTable.join(tablesToJoin)
        ##AVERAGE...A LOT OF SUBTLETY IN STRENGTH OF PREDICTION
        transformedPreds = pd.DataFrame(predsTable.apply(
            lambda x: dataAck.computePosition(x), axis=1),
                                        columns=["Predictions"]).dropna()
        dailyFactorReturn = dataAck.getDailyFactorReturn(
            self.targetTicker, dataOfInterest)
        transformedPreds = transformedPreds.join(dailyFactorReturn).dropna()
        returnStream = pd.DataFrame(transformedPreds.apply(
            lambda x: x[0] * x[1], axis=1),
                                    columns=["Algo Return"])
        factorReturn = pd.DataFrame(transformedPreds[["Factor Return"]])
        predictions = pd.DataFrame(transformedPreds[["Predictions"]])
        estimatedSlippageLoss = portfolioGeneration.estimateTransactionCost(
            predictions)
        estimatedSlippageLoss.columns = returnStream.columns
        slippageAdjustedReturn = (returnStream -
                                  estimatedSlippageLoss).dropna()

        return returnStream, factorReturn, predictions, slippageAdjustedReturn, rawPredictions
    def runModelsChunksSkipMP(self, dataOfInterest, daysToCheck = None, earlyStop=False):
        xVals, yVals, yIndex, xToday = self.generateWindows(dataOfInterest)
        mpEngine = mp.get_context('fork')
        with mpEngine.Manager() as manager:
            returnDict = manager.dict()
            
            identifiersToCheck = []
            
            for i in range(len(xVals) - 44): ##44 is lag...should not overlap with any other predictions or will ruin validity of walkforward optimization
                if i < 600:
                    ##MIN TRAINING
                    continue
                identifiersToCheck.append(str(i))
                
            if daysToCheck is not None:
                identifiersToCheck = identifiersToCheck[-daysToCheck:]


            ##FIRST CHECK FIRST 500 IDENTIFIERS AND THEN IF GOOD CONTINUE
            

            identifierWindows = [identifiersToCheck[:252], identifiersToCheck[252:600], identifiersToCheck[600:900], identifiersToCheck[900:1200], identifiersToCheck[1200:]] ##EXACTLY TWO YEARS
            if earlyStop == False:
                identifierWindows = [identifiersToCheck]
            returnStream = None
            factorReturn = None
            predictions = None
            slippageAdjustedReturn = None
            rawPredictions = None
            shortSeen = 0 if earlyStop == True else -1
            for clippedIdentifiers in identifierWindows:
                
                splitIdentifiers = np.array_split(np.array(clippedIdentifiers), 4)
                
                
                runningP = []
                k = 0
                for identifiers in splitIdentifiers:
                    p = mpEngine.Process(target=CurvePredictor.runDayChunking, args=(self, xVals, yVals, identifiers, returnDict,k))
                    p.start()
                    runningP.append(p)
                    
                    k += 1
                    

                while len(runningP) > 0:
                    newP = []
                    for p in runningP:
                        if p.is_alive() == True:
                            newP.append(p)
                        else:
                            p.join()
                    runningP = newP
                    
                
                preds = []
                actuals = []
                days = []
                for i in clippedIdentifiers:
                    preds.append(returnDict[i])
                    actuals.append(yVals[int(i) + 44])
                    days.append(yIndex[int(i) + 44])

                ##CREATE ACCURATE BLENDING ACROSS DAYS
                predsTable = pd.DataFrame(preds, index=days, columns=["Predictions"])
                
                i = 1
                tablesToJoin = []
                while i < self.predictionDistance:
                    thisTable = predsTable.shift(i)
                    thisTable.columns = ["Predictions_" + str(i)]
                    tablesToJoin.append(thisTable)
                    i += 1
                
                predsTable = predsTable.join(tablesToJoin)
                transformedPreds = pd.DataFrame(predsTable.apply(lambda x:dataAck.computePosition(x), axis=1), columns=["Predictions"]).dropna()
                dailyFactorReturn = dataAck.getDailyFactorReturn(self.targetTicker, dataOfInterest)
                transformedPreds = transformedPreds.join(dailyFactorReturn).dropna()
                returnStream = pd.DataFrame(transformedPreds.apply(lambda x:x[0] * x[1], axis=1), columns=["Algo Return"]) if returnStream is None else pd.concat([returnStream, pd.DataFrame(transformedPreds.apply(lambda x:x[0] * x[1], axis=1), columns=["Algo Return"])])
                factorReturn = pd.DataFrame(transformedPreds[["Factor Return"]]) if factorReturn is None else pd.concat([factorReturn, pd.DataFrame(transformedPreds[["Factor Return"]])])
                predictions = pd.DataFrame(transformedPreds[["Predictions"]]) if predictions is None else pd.concat([predictions, pd.DataFrame(transformedPreds[["Predictions"]])])
                rawPredictions = pd.DataFrame(preds, index=days, columns=["Predictions"]) if rawPredictions is None else pd.concat([rawPredictions, pd.DataFrame(preds, index=days, columns=["Predictions"])])
                
                alpha, beta = empyrical.alpha_beta(returnStream, factorReturn)
                activity = np.count_nonzero(returnStream)/float(len(returnStream))
                rawBeta = abs(empyrical.alpha_beta(returnStream.apply(lambda x:dataAck.applyBinary(x), axis=0), factorReturn.apply(lambda x:dataAck.applyBinary(x), axis=0))[1])
                shortSharpe = empyrical.sharpe_ratio(returnStream)
                activity = np.count_nonzero(returnStream)/float(len(returnStream))
                algoAnnualReturn = empyrical.annual_return(returnStream.values)[0]
                algoVol = empyrical.annual_volatility(returnStream.values)
                factorAnnualReturn = empyrical.annual_return(factorReturn.values)[0]
                factorVol = empyrical.annual_volatility(factorReturn.values)
                treynor = ((empyrical.annual_return(returnStream.values)[0] - empyrical.annual_return(factorReturn.values)[0]) \
                           / abs(empyrical.beta(returnStream, factorReturn)))
                sharpeDiff = empyrical.sharpe_ratio(returnStream) - empyrical.sharpe_ratio(factorReturn)
                relativeSharpe = sharpeDiff / empyrical.sharpe_ratio(factorReturn) * (empyrical.sharpe_ratio(factorReturn)/abs(empyrical.sharpe_ratio(factorReturn)))
                stability = empyrical.stability_of_timeseries(returnStream)

                ##CALCULATE SHARPE WITH SLIPPAGE
                estimatedSlippageLoss = portfolioGeneration.estimateTransactionCost(predictions)
                estimatedSlippageLoss.columns = returnStream.columns
                slippageAdjustedReturn = (returnStream - estimatedSlippageLoss).dropna()
                slippageSharpe = empyrical.sharpe_ratio(slippageAdjustedReturn)
                sharpeDiffSlippage = empyrical.sharpe_ratio(slippageAdjustedReturn) - empyrical.sharpe_ratio(factorReturn)
                relativeSharpeSlippage = sharpeDiffSlippage / empyrical.sharpe_ratio(factorReturn) * (empyrical.sharpe_ratio(factorReturn)/abs(empyrical.sharpe_ratio(factorReturn)))
                profitability = len((returnStream.values)[returnStream.values > 0])/len(returnStream.values)
                

                rollingProfitability = returnStream.rolling(45, min_periods=45).apply(lambda x:len((x)[x > 0])/len(x)).dropna().values
                minRollingProfitability = np.percentile(rollingProfitability, 1)
                twentyFifthPercentileRollingProfitablity = np.percentile(rollingProfitability, 25)


                if np.isnan(shortSharpe) == True:
                    return None, {"sharpe":shortSharpe}, None, None, None

                elif (profitability < 0.4  or activity < 0.3 or abs(rawBeta) > 0.4 or stability < 0.3) and shortSeen == 0:
                    return None, {
                            "sharpe":shortSharpe, ##OVERLOADED IN FAIL
                            "activity":activity,
                            "factorSharpe":empyrical.sharpe_ratio(factorReturn),
                            "sharpeSlippage":slippageSharpe,
                            "beta":abs(beta),
                            "alpha":alpha,
                            "activity":activity,
                            "treynor":treynor,
                            "period":"first 252 days",
                            "algoReturn":algoAnnualReturn,
                            "algoVol":algoVol,
                            "factorReturn":factorAnnualReturn,
                            "factorVol":factorVol,
                            "sharpeDiff":sharpeDiff,
                            "relativeSharpe":relativeSharpe,
                            "sharpeDiffSlippage":sharpeDiffSlippage,
                            "relativeSharpeSlippage":relativeSharpeSlippage,
                            "rawBeta":rawBeta,
                            "minRollingProfitability":minRollingProfitability,
                            "stability":stability,
                            "twentyFifthPercentileRollingProfitablity":twentyFifthPercentileRollingProfitablity,
                            "profitability":profitability
                    }, None, None, None
                
                elif abs(rawBeta) > 0.33 or activity < 0.3 or stability < 0.4 or twentyFifthPercentileRollingProfitablity < 0.41 \
                     or minRollingProfitability < 0.3 or profitability < 0.46:
                    periodName = "first 600 days"
                    if shortSeen == 2:
                        periodName = "first 900 days"
                    elif shortSeen == 3:
                        periodName = "first 1200 days"
                    return None, {
                            "sharpe":shortSharpe, ##OVERLOADED IN FAIL
                            "activity":activity,
                            "factorSharpe":empyrical.sharpe_ratio(factorReturn),
                            "sharpeSlippage":slippageSharpe,
                            "alpha":alpha,
                            "beta":abs(beta),
                            "activity":activity,
                            "treynor":treynor,
                            "period":periodName,
                            "algoReturn":algoAnnualReturn,
                            "algoVol":algoVol,
                            "factorReturn":factorAnnualReturn,
                            "factorVol":factorVol,
                            "minRollingProfitability":minRollingProfitability,
                            "sharpeDiff":sharpeDiff,
                            "relativeSharpe":relativeSharpe,
                            "sharpeDiffSlippage":sharpeDiffSlippage,
                            "relativeSharpeSlippage":relativeSharpeSlippage,
                            "rawBeta":rawBeta,
                            "stability":stability,
                            "twentyFifthPercentileRollingProfitablity":twentyFifthPercentileRollingProfitablity,
                            "profitability":profitability
                    }, None, None, None
                    
                elif shortSeen < 4:
                    print("CONTINUING", "SHARPE:", shortSharpe, "SHARPE DIFF:", sharpeDiff, "RAW BETA:", rawBeta, "TREYNOR:", treynor)
               
                shortSeen += 1

            return returnStream, factorReturn, predictions, slippageAdjustedReturn, rawPredictions