def RunTradingModelBuyHold(tm: TradingModel, ticker: str):
    currentPrices = tm.GetPriceSnapshot()
    if tm.verbose:
        print(currentPrices.snapShotDate, currentPrices.nextDayTarget)
    if not currentPrices == None:
        if tm.TranchesAvailable() > 0 and tm.FundsAvailable(
        ) > currentPrices.high:
            tm.PlaceBuy(ticker, currentPrices.low, True)
def RunModel(modelName: str,
             modelFunction,
             ticker: str,
             startDate: str,
             durationInYears: int,
             portfolioSize: int,
             saveHistoryToFile: bool = True,
             returndailyValues: bool = False,
             verbose: bool = False):
    #Performs the logic of the given model over a period of time to evaluate the performance
    modelName = modelName + '_' + ticker
    print('Running model ' + modelName)
    tm = TradingModel(modelName=modelName,
                      startingTicker=ticker,
                      startDate=startDate,
                      durationInYears=durationInYears,
                      totalFunds=portfolioSize,
                      tranchSize=round(portfolioSize / 10),
                      verbose=verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model for ' +
              str(startDate))
        if returndailyValues: return pd.DataFrame()
        else: return portfolioSize
    else:
        while not tm.ModelCompleted():
            modelFunction(tm, ticker)
            tm.ProcessDay()
            if tm.AccountingError():
                print(
                    'Accounting error.  The numbers do not add up correctly.  Terminating model run.',
                    tm.currentDate)
                tm.PositionSummary()
                #tm.PrintPositions()
                break
        cash, asset = tm.Value()
        #print('Ending Value: ', cash + asset, '(Cash', cash, ', Asset', asset, ')')
        tradeCount = len(tm.tradeHistory)
        RecordPerformance(ModelName=modelName,
                          StartDate=startDate,
                          EndDate=tm.currentDate,
                          StartValue=portfolioSize,
                          EndValue=(cash + asset),
                          TradeCount=tradeCount)
        if returndailyValues:
            tm.CloseModel(verbose, saveHistoryToFile)
            return tm.GetDailyValue(
            )  #return daily value for model comparisons
        else:
            return tm.CloseModel(
                verbose, saveHistoryToFile
            )  #return simple closing value to view net effect
Exemple #3
0
def RunTradingModelBuyHold(tm: TradingModel, ticker: str):
    #Baseline model, buy and hold
    currentPrices = tm.GetPriceSnapshot()
    if tm.verbose:
        print(currentPrices.snapShotDate, currentPrices.nextDayTarget)
    if not currentPrices == None:
        for i in range(tm._tranchCount):
            available, buyPending, sellPending, longPositions = tm.PositionSummary(
            )
            if tm.TranchesAvailable() > 0 and tm.FundsAvailable(
            ) > currentPrices.high:
                tm.PlaceBuy(ticker, currentPrices.low, True)
            if available == 0: break
def AlignPositions(tm:TradingModel, targetPositions:pd.DataFrame, stockCount:int, allocateByPointValue:bool= False, verbose:bool = False):
	#Helper function.  Performs necessary Buy/Sells to get from current positions to target positions
	print(targetPositions)
	TotalTranches = tm._tranchCount
	targetPositions=pd.DataFrame(targetPositions.groupby(['Ticker','pointValue']).size()).reset_index()
	targetPositions.set_index(['Ticker'], inplace=True)
	targetPositions.rename(columns={0:'TargetHoldings'}, inplace=True)
	targetPositions.sort_values(by=['TargetHoldings', 'pointValue'], axis=0, ascending=False, inplace=True, kind='quicksort', na_position='last') 
	targetPositions = targetPositions[:stockCount]
	print(targetPositions)
	if allocateByPointValue:
		TotalPoints = targetPositions['pointValue'].sum()  
		scale = TotalTranches/TotalPoints
		print('scale', TotalPoints, TotalTranches, scale)
		targetPositions.loc[:, 'TargetHoldings'] =  round(targetPositions.loc[:, 'TargetHoldings'] * targetPositions.loc[:, 'pointValue'] * scale)
	else:
		TotalTargets = targetPositions['TargetHoldings'].sum()  
		scale = TotalTranches/TotalTargets
		print('scale', TotalTargets, TotalTranches, scale)
		targetPositions.loc[:, 'TargetHoldings'] =  round(targetPositions.loc[:, 'TargetHoldings'] * scale)
	print(targetPositions)
	currentPositions = tm.GetPositions(asDataFrame=True)
	if len(currentPositions) > 0:	#evaluate the difference between current holdings and target, act accordingly
		targetPositions = targetPositions.join(currentPositions, how='outer')
		targetPositions.fillna(value=0, inplace=True)				
		targetPositions['Difference'] = targetPositions['TargetHoldings'] - targetPositions['CurrentHoldings']
		print(targetPositions)
		for i in range(len(targetPositions)):
			sells = int(targetPositions.iloc[i]['Difference'])
			if sells < 0:
				t = targetPositions.index.values[i]
				print('Sell ' + str(abs(sells)) + ' ' + t)
				for _ in range(abs(sells)): 
					tm.PlaceSell(ticker=t, price=1, marketOrder=True, expireAfterDays=10, verbose=verbose)
		tm.ProcessDay(withIncrement=False)
		for i in range(len(targetPositions)):
			buys = int(targetPositions.iloc[i]['Difference'])
			if buys > 0:
				t = targetPositions.index.values[i]
				print('Buy ' + str(buys) + ' ' + t)
				for _ in range(buys):
					tm.PlaceBuy(ticker=t, price=1, marketOrder=True, expireAfterDays=10, verbose=verbose)								
		tm.ProcessDay(withIncrement=False)
	elif len(targetPositions) > 0:	
		for i in range(len(targetPositions)):
			buys = int(targetPositions.iloc[i]['TargetHoldings'])
			if buys > 0:
				t = targetPositions.index.values[i]
				print(t)
				print(buys)
				print('Buy ' + str(buys) + ' ' + t)
				for _ in range(buys):
					tm.PlaceBuy(ticker=t, price=1, marketOrder=True, expireAfterDays=10, verbose=verbose)								
		tm.ProcessDay(withIncrement=False)
	print(tm.GetPositions(asDataFrame=True))
	print(tm.PositionSummary())
def RunPriceMomentum(tickerList:list, startDate:str='1/1/1982', durationInYears:int=36, stockCount:int=9, ReEvaluationInterval:int=20, filterOption:int=3, longHistory:int=365, shortHistory:int=90, minPercentGain=0.05, maxVolatility=.12, portfolioSize:int=30000, returndailyValues:bool=False, verbose:bool=False):
	#Choose stockCount stocks with the greatest long term (longHistory days) price appreciation, using different filter options defined in the StockPicker class
	#shortHistory is a shorter time frame (like 90 days) used differently by different filters
	#ReEvaluationInterval is how often to re-evaluate our choices, ideally this should be very short and not matter, otherwise the date selection is biased.
	startDate = ToDate(startDate)
	endDate =  AddDays(startDate, 365 * durationInYears)
	picker = StockPicker(AddDays(startDate, -730), endDate) #Include earlier dates for statistics
	for t in tickerList:
		picker.AddTicker(t)
	tm = TradingModel(modelName='PriceMomentumShort_longHistory_' + str(longHistory) +'_shortHistory_' + str(shortHistory) + '_reeval_' + str(ReEvaluationInterval) + '_stockcount_' + str(stockCount) + '_filter' + str(filterOption) + '_' + str(minPercentGain) + str(maxVolatility), startingTicker='^SPX', startDate=startDate, durationInYears=durationInYears, totalFunds=portfolioSize, tranchSize=portfolioSize/stockCount, verbose=verbose)
	dayCounter = 0
	if not tm.modelReady:
		print('Unable to initialize price history for PriceMomentum date ' + str(startDate))
		return 0
	else:
		while not tm.ModelCompleted():
			currentDate =  tm.currentDate
			if dayCounter ==0:
				print('\n')
				print(currentDate)
				c, a = tm.Value()
				print(tm.modelName, int(c), int(a), int(c+a))
				print('available/buy/sell/long',tm.PositionSummary())
				candidates = picker.GetHighestPriceMomentum(currentDate, longHistoryDays=longHistory, shortHistoryDays=shortHistory, stocksToReturn=stockCount, filterOption=filterOption, minPercentGain=minPercentGain, maxVolatility=maxVolatility)
				AlignPositions(tm=tm, targetPositions=candidates, stockCount=stockCount, allocateByPointValue=False)
			tm.ProcessDay()
			dayCounter+=1
			if dayCounter >= ReEvaluationInterval: dayCounter=0

		cv1 = tm.CloseModel(plotResults=False, saveHistoryToFile=((durationInYears>1) or verbose))
		if returndailyValues:
			return tm.GetDailyValue()
		else:
			return cv1
Exemple #6
0
def RunModel(modelName: str,
             modelFunction,
             ticker: str,
             startDate: str,
             durationInYears: int,
             totalFunds: int,
             saveHistoryToFile: bool = True,
             returndailyValues: bool = False,
             verbose: bool = False):
    modelName = modelName + '_' + ticker
    tm = TradingModel(modelName=modelName,
                      startingTicker=ticker,
                      startDate=startDate,
                      durationInYears=durationInYears,
                      totalFunds=totalFunds,
                      verbose=verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model for ' +
              str(startDate))
        if returndailyValues: return pandas.DataFrame()
        else: return totalFunds
    else:
        while not tm.ModelCompleted():
            tm.ProcessDay()
            modelFunction(tm, ticker)
            if tm.AccountingError():
                print(
                    'Accounting error.  The numbers do not add up correctly.')
                break
        if returndailyValues:
            tm.CloseModel(verbose, saveHistoryToFile)
            return tm.GetDailyValue()  #return daily value
        else:
            return tm.CloseModel(verbose,
                                 saveHistoryToFile)  #return closing value
def RunTradingModelQLearn(ticker: str,
                          startDate: str,
                          durationInYears: int,
                          totalFunds: int,
                          verbose: bool = False,
                          saveHistoryToFile: bool = True,
                          returndailyValues: bool = False):
    Actions = [
        'Hold', 'BuyMarket', 'BuyAgressiveLeve10', 'BuyAgressiveLeve11',
        'BuyAgressiveLeve12', 'SellMarket', 'SellAgressiveLeve10',
        'SellAgressiveLeve11', 'SellAgressiveLeve12'
    ]
    modelName = 'QLearn' + '_' + ticker
    tm = TradingModel(modelName, ticker, startDate, durationInYears,
                      totalFunds, verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model for ' +
              str(startDate))
        if returndailyValues: return pandas.DataFrame()
        else: return totalFunds
    else:
        while not tm.ModelCompleted():
            tm.ProcessDay()
            currentPrices = tm.GetPriceSnapshot()
            if not currentPrices == None:
                pass
                #do stuff
        if returndailyValues:
            tm.CloseModel(verbose, saveHistoryToFile)
            return tm.GetdailyValue()  #return daily value
        else:
            return tm.CloseModel(verbose,
                                 saveHistoryToFile)  #return closing value
def RunTradingModelSeasonal(tm: TradingModel, ticker: str):
    SellMonth = 4  #April
    BuyMonth = 10  #October
    currentPrices = tm.GetPriceSnapshot()
    if not currentPrices == None:
        low = currentPrices.low
        high = currentPrices.high
        m = tm.currentDate.month
        available, buyPending, sellPending, longPositions = tm.PositionSummary(
        )
        if m >= SellMonth and m <= BuyMonth:
            if longPositions > 0: tm.PlaceSell(ticker, high, True)
        else:
            if available > 0 and tm.FundsAvailable() > high:
                tm.PlaceBuy(ticker, low, True)
Exemple #9
0
def RunTradingModelSeasonal(tm: TradingModel, ticker: str):
    #Buy in November, sell in May
    SellMonth = 5
    BuyMonth = 11
    currentPrices = tm.GetPriceSnapshot()
    if not currentPrices == None:
        low = currentPrices.low
        high = currentPrices.high
        m = tm.currentDate.month
        for i in range(tm._tranchCount):
            available, buyPending, sellPending, longPositions = tm.PositionSummary(
            )
            if m >= SellMonth and m <= BuyMonth:
                if longPositions > 0:
                    tm.PlaceSell(ticker, high, True)
                else:
                    break
            else:
                if available > 0 and tm.FundsAvailable() > high:
                    tm.PlaceBuy(ticker, low, True)
                else:
                    break
Exemple #10
0
def RunTradingModelFirstHalfOfMonth(tm: TradingModel, ticker: str):
    #From Robert Ariel's observations, most gains are in the first half of the month
    BuyDay = 25  #Buy at the end of the month, after the 25th
    SellDay = 15  #Sell mid month, after the 15th
    currentPrices = tm.GetPriceSnapshot()
    if not currentPrices == None:
        low = currentPrices.low
        high = currentPrices.high
        d = tm.currentDate.day
        for i in range(tm._tranchCount):
            available, buyPending, sellPending, longPositions = tm.PositionSummary(
            )
            if d >= BuyDay or d < 3:
                if available > 0 and tm.FundsAvailable() > high:
                    tm.PlaceBuy(ticker, low, True)
                else:
                    break
            elif d >= SellDay:
                if longPositions > 0:
                    tm.PlaceSell(ticker, high, True)
                else:
                    break
            else:
                break
def RunModel(modelName: str,
             modelFunction,
             ticker: str,
             startDate: str,
             durationInYears: int,
             portfolioSize: int,
             saveHistoryToFile: bool = True,
             returndailyValues: bool = False,
             verbose: bool = False):
    modelName = modelName + '_' + ticker
    tm = TradingModel(modelName=modelName,
                      startingTicker=ticker,
                      startDate=startDate,
                      durationInYears=durationInYears,
                      totalFunds=portfolioSize,
                      verbose=verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model for ' +
              str(startDate))
        if returndailyValues: return pd.DataFrame()
        else: return portfolioSize
    else:
        while not tm.ModelCompleted():
            tm.ProcessDay()
            modelFunction(tm, ticker)
            if tm.AccountingError():
                print(
                    'Accounting error.  The numbers do not add up correctly.  Terminating model run.'
                )
                tm.PositionSummary()
                #tm.PrintPositions()
                break
        if returndailyValues:
            tm.CloseModel(verbose, saveHistoryToFile)
            return tm.GetDailyValue(
            )  #return daily value for model comparisons
        else:
            return tm.CloseModel(
                verbose, saveHistoryToFile
            )  #return simple closing value to view net effect
Exemple #12
0
def RunBuyHold(ticker: str,
               startDate: datetime,
               durationInYears: int,
               ReEvaluationInterval: int = 20,
               portfolioSize: int = 30000,
               verbose: bool = False):
    modelName = 'BuyHold_' + (ticker) + '_' + startDate[-4:]
    tm = TradingModel(modelName=modelName,
                      startingTicker=ticker,
                      startDate=startDate,
                      durationInYears=durationInYears,
                      totalFunds=portfolioSize,
                      tranchSize=portfolioSize / 10,
                      verbose=verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model BuyHold date ' +
              str(startDate))
        return 0
    else:
        dayCounter = 0
        while not tm.ModelCompleted():
            if dayCounter == 0:
                tm.SellAllPositions(tm.currentDate)
                i = 0
                while tm.TranchesAvailable() and i < 100:
                    tm.PlaceBuy(ticker=ticker,
                                price=1,
                                marketOrder=True,
                                expireAfterDays=10,
                                verbose=verbose)
                    i += 1
            dayCounter += 1
            if dayCounter >= ReEvaluationInterval: dayCounter = 0
            tm.ProcessDay()
        cash, asset = tm.Value()
        print('Ending Value: ', cash + asset, '(Cash', cash, ', Asset', asset,
              ')')
        return tm.CloseModel(plotResults=False, saveHistoryToFile=verbose)
def RunTradingModelBuyHold(ticker: str,
                           startDate: str,
                           durationInYears: int,
                           totalFunds: int,
                           verbose: bool = False,
                           saveHistoryToFile: bool = True,
                           returndailyValues: bool = False):
    modelName = 'BuyHold' + '_' + ticker
    tm = TradingModel(modelName, ticker, startDate, durationInYears,
                      totalFunds, verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model for ' +
              str(startDate))
        if returndailyValues: return pandas.DataFrame()
        else: return totalFunds
    else:
        while not tm.ModelCompleted():
            tm.ProcessDay()
            currentPrices = tm.GetPriceSnapshot()
            if not currentPrices == None:
                if tm.TraunchesAvailable(
                ) and tm.FundsAvailable() > currentPrices.high:
                    tm.PlaceBuy(ticker, currentPrices.low, True)
            if tm.AccountingError(): break
        if returndailyValues:
            tm.CloseModel(verbose, saveHistoryToFile)
            return tm.GetdailyValue()  #return daily value
        else:
            return tm.CloseModel(verbose,
                                 saveHistoryToFile)  #return closing value
def RunTradingModelSwingTrend(ticker: str,
                              startDate: str,
                              durationInYears: int,
                              totalFunds: int,
                              verbose: bool = False,
                              saveHistoryToFile: bool = True,
                              returndailyValues: bool = False):
    #Give it a date range, some money, and a stock, it will execute a strategy and return the results
    #minDeviationToTrade = .025
    minActionableSlope = 0.002
    trendState = 'Flat'  #++,--,+-,-+,Flat
    prevTrendState = ''
    trendDuration = 0

    modelName = 'SwingTrend' + '_' + ticker
    tm = TradingModel(modelName, ticker, startDate, durationInYears,
                      totalFunds, verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model for ' +
              str(startDate))
        if returndailyValues: return pandas.DataFrame()
        else: return totalFunds
    else:
        while not tm.ModelCompleted():
            tm.ProcessDay()
            p = tm.GetPriceSnapshot()
            if not p == None:
                available, buyPending, sellPending, longPositions = tm.GetPositionSummary(
                )
                maxPositions = available + buyPending + sellPending + longPositions
                targetBuy = p.nextDayTarget * (1 + p.fiveDayDeviation / 2)
                targetSell = p.nextDayTarget * (1 - p.fiveDayDeviation / 2)
                if p.longEMASlope >= minActionableSlope and p.shortEMASlope >= minActionableSlope:  #++	Positive trend, 70% long
                    trendState = '++'
                    if p.low > p.channelHigh:  #Over Bought
                        if sellPending < 3 and longPositions > 7:
                            tm.PlaceSell(ticker, targetSell * (1.03), False,
                                         10)
                    elif p.low < p.channelLow:  #Still early
                        if buyPending < 3 and longPositions < 6:
                            tm.PlaceBuy(ticker, targetBuy, True)
                        if trendDuration > 1 and buyPending < 3:
                            tm.PlaceBuy(ticker, targetBuy, True)
                    else:
                        if buyPending < 3 and longPositions < 6:
                            tm.PlaceBuy(ticker, targetBuy, False)
                    if buyPending < 5 and longPositions < maxPositions:
                        tm.PlaceBuy(ticker, targetBuy, False)
                elif p.longEMASlope >= minActionableSlope and p.shortEMASlope < minActionableSlope:  #+- Correction or early downturn
                    trendState = '+-'
                    if p.low > p.channelHigh:  #Over Bought, try to get out
                        if sellPending < 3 and longPositions > 7:
                            tm.PlaceSell(ticker, targetSell, False, 3)
                    elif p.low < p.channelLow and p.high > p.channelLow:  #Deep correction
                        if sellPending < 3 and longPositions > 7:
                            tm.PlaceSell(ticker, targetSell, False, 3)
                    else:
                        pass
                elif p.longEMASlope < -minActionableSlope and p.shortEMASlope < -minActionableSlope:  #-- Negative trend, aim for < 30% long
                    trendState = '--'
                    if p.high < p.channelLow:  #Over sold
                        if buyPending < 3 and longPositions < 6:
                            tm.PlaceBuy(ticker, targetBuy * .95, False, 2)
                    elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low, early down or up
                        pass
                    else:
                        if sellPending < 5 and longPositions > 3:
                            tm.PlaceSell(ticker, targetSell, True)
                            if trendDuration > 1:
                                tm.PlaceSell(ticker, targetSell, True)
                    if sellPending < 5 and longPositions > 3:
                        tm.PlaceSell(ticker, targetSell, False, 2)
                        tm.PlaceSell(ticker, targetSell, False, 2)
                elif p.longEMASlope < (
                        -1 * minActionableSlope) and p.shortEMASlope < (
                            -1 *
                            minActionableSlope):  #-+ Bounce or early recovery
                    trendState = '-+'
                    if p.high < p.channelLow:  #Over sold
                        pass
                    elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low
                        if sellPending < 3 and longPositions > 3:
                            tm.PlaceSell(ticker, targetSell, False, 3)
                    else:
                        pass
                else:  #flat, aim for 70% long
                    trendState = 'Flat'
                    if p.low > p.channelHigh:  #Over Bought
                        if sellPending < 3 and longPositions > 7:
                            tm.PlaceSell(ticker, targetSell * (1.03), False,
                                         10)
                    elif p.high < p.channelLow:  #Over sold
                        if buyPending < 3 and longPositions < 8:
                            tm.PlaceBuy(ticker, targetBuy, False, 5)
                        if buyPending < 4:
                            tm.PlaceBuy(ticker, targetBuy, False, 5)
                    else:
                        pass
                    if sellPending < 3 and longPositions > 7:
                        tm.PlaceSell(ticker, targetSell, False, 5)
                    if buyPending < 3 and longPositions < maxPositions:
                        tm.PlaceBuy(ticker, targetBuy, False, 5)
                if trendState == prevTrendState:
                    trendDuration = trendDuration + 1
                else:
                    trendDuration = 0
            if tm.AccountingError(): break
        if returndailyValues:
            tm.CloseModel(verbose, saveHistoryToFile)
            return tm.GetdailyValue()  #return daily value
        else:
            return tm.CloseModel(verbose,
                                 saveHistoryToFile)  #return closing value
def RunTradingModelSeasonal(ticker: str,
                            startDate: str,
                            durationInYears: int,
                            totalFunds: int,
                            verbose: bool = False,
                            saveHistoryToFile: bool = True,
                            returndailyValues: bool = False):
    modelName = 'Seasonal' + '_' + ticker
    tm = TradingModel(modelName, ticker, startDate, durationInYears,
                      totalFunds, verbose)
    if not tm.modelReady:
        print('Unable to initialize price history for model for ' +
              str(startDate))
        if returndailyValues: return pandas.DataFrame()
        else: return totalFunds
    else:
        while not tm.ModelCompleted():
            tm.ProcessDay()
            currentPrices = tm.GetPriceSnapshot()
            if not currentPrices == None:
                low = currentPrices.low
                high = currentPrices.high
                m = tm.currentDate.month
                available, buyPending, sellPending, longPositions = tm.GetPositionSummary(
                )
                if m >= 11 or m <= 4:  #Buy if Nov through April, else sell
                    if available > 0 and tm.FundsAvailable() > high:
                        tm.PlaceBuy(ticker, low, True)
                else:
                    if longPositions > 0: tm.PlaceSell(ticker, high, True)
            if tm.AccountingError(): break
        if returndailyValues:
            tm.CloseModel(verbose, saveHistoryToFile)
            return tm.GetdailyValue()  #return daily value
        else:
            return tm.CloseModel(verbose,
                                 saveHistoryToFile)  #return closing value
Exemple #16
0
def RunTradingModelSwingTrend(tm: TradingModel, ticker: str):
    #Combines trending model with targeted "swing" buys, attempting to gain better deals by anticipating daily price fluctuations
    minActionableSlope = 0.002
    prevTrendState, trendDuration = tm.GetCustomValues()
    if prevTrendState == None: prevTrendState = ''
    if trendDuration == None: trendDuration = 0
    p = tm.GetPriceSnapshot()
    if not p == None:
        for i in range(tm._tranchCount):
            available, buyPending, sellPending, longPositions = tm.PositionSummary(
            )
            maxPositions = available + buyPending + sellPending + longPositions
            targetBuy = p.nextDayTarget * (1 + p.fiveDayDeviation / 2)
            targetSell = p.nextDayTarget * (1 - p.fiveDayDeviation / 2)
            if p.longEMASlope >= minActionableSlope and p.shortEMASlope >= minActionableSlope:  #++	Positive trend, 70% long
                trendState = '++'
                if p.low > p.channelHigh:  #Over Bought
                    if sellPending < 3 and longPositions > 7:
                        tm.PlaceSell(ticker, targetSell * (1.03), False, 10)
                elif p.low < p.channelLow:  #Still early
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy, True)
                    if trendDuration > 1 and buyPending < 3:
                        tm.PlaceBuy(ticker, targetBuy, True)
                else:
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy, False)
                if buyPending < 5 and longPositions < maxPositions:
                    tm.PlaceBuy(ticker, targetBuy, False)
            elif p.longEMASlope >= minActionableSlope and p.shortEMASlope < minActionableSlope:  #+- Correction or early downturn
                trendState = '+-'
                if p.low > p.channelHigh:  #Over Bought, try to get out
                    if sellPending < 3 and longPositions > 7:
                        tm.PlaceSell(ticker, targetSell, False, 3)
                elif p.low < p.channelLow and p.high > p.channelLow:  #Deep correction
                    if sellPending < 3 and longPositions > 7:
                        tm.PlaceSell(ticker, targetSell, False, 3)
                else:
                    pass
            elif p.longEMASlope < -minActionableSlope and p.shortEMASlope < -minActionableSlope:  #-- Negative trend, aim for < 30% long
                trendState = '--'
                if p.high < p.channelLow:  #Over sold
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy * .95, False, 2)
                elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low, early down or up
                    pass
                else:
                    if sellPending < 5 and longPositions > 3:
                        tm.PlaceSell(ticker, targetSell, True)
                        if trendDuration > 1:
                            tm.PlaceSell(ticker, targetSell, True)
                if sellPending < 5 and longPositions > 3:
                    tm.PlaceSell(ticker, targetSell, False, 2)
                    tm.PlaceSell(ticker, targetSell, False, 2)
            elif p.longEMASlope < (
                    -1 * minActionableSlope) and p.shortEMASlope < (
                        -1 * minActionableSlope):  #-+ Bounce or early recovery
                trendState = '-+'
                if p.high < p.channelLow:  #Over sold
                    pass
                elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low
                    if sellPending < 3 and longPositions > 3:
                        tm.PlaceSell(ticker, targetSell, False, 3)
                else:
                    pass
            else:  #flat, aim for 70% long
                trendState = 'Flat'
                if p.low > p.channelHigh:  #Over Bought
                    if sellPending < 3 and longPositions > 7:
                        tm.PlaceSell(ticker, targetSell * (1.03), False, 10)
                elif p.high < p.channelLow:  #Over sold
                    if buyPending < 3 and longPositions < 8:
                        tm.PlaceBuy(ticker, targetBuy, False, 5)
                    if buyPending < 4: tm.PlaceBuy(ticker, targetBuy, False, 5)
                else:
                    pass
                if sellPending < 3 and longPositions > 7:
                    tm.PlaceSell(ticker, targetSell, False, 5)
                if buyPending < 3 and longPositions < maxPositions:
                    tm.PlaceBuy(ticker, targetBuy, False, 5)
            if trendState == prevTrendState:
                trendDuration = trendDuration + 1
            else:
                trendDuration = 0
        tm.SetCustomValues(prevTrendState, trendDuration)
Exemple #17
0
def RunTradingModelTrending(tm: TradingModel, ticker: str):
    #This compares the slope of short term (6 day) and long term (18 day) exponential moving averages to determine buying opportunities.  Positive, negative, or flat slopes
    #trend states: ++,--,+-,-+,Flat
    minActionableSlope = 0.002
    prevTrendState, trendDuration = tm.GetCustomValues()
    if prevTrendState == None: prevTrendState = ''
    if trendDuration == None: trendDuration = 0
    p = tm.GetPriceSnapshot()
    if not p == None:
        available, buyPending, sellPending, longPositions = tm.PositionSummary(
        )
        maxPositions = available + buyPending + sellPending + longPositions
        targetBuy = p.nextDayTarget * (1 + p.fiveDayDeviation / 2)
        targetSell = p.nextDayTarget * (1 - p.fiveDayDeviation / 2)
        for i in range(tm._tranchCount):
            if p.longEMASlope >= minActionableSlope and p.shortEMASlope >= minActionableSlope:  #++	Positive trend, 100% long
                trendState = '++'
                if p.low > p.channelHigh:  #Over Bought
                    pass
                elif p.low < p.channelLow:  #Still early
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy, True)
                    if trendDuration > 1 and buyPending < 3:
                        tm.PlaceBuy(ticker, targetBuy, True)
                else:
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy, True)
                if buyPending < 5 and longPositions < maxPositions:
                    tm.PlaceBuy(ticker, targetBuy, False, 3)
            elif p.longEMASlope >= minActionableSlope and p.shortEMASlope < minActionableSlope:  #+- Correction or early downturn
                trendState = '+-'
                if p.low > p.channelHigh:  #Over Bought, try to get out
                    if sellPending < 3 and longPositions > 7:
                        tm.PlaceSell(ticker, targetSell * .98, False, 3)
                elif p.low < p.channelLow and p.high > p.channelLow:  #Deep correction
                    if sellPending < 3 and longPositions > 7:
                        tm.PlaceSell(ticker, targetSell, False, 3)
                else:
                    pass
            elif p.longEMASlope < -minActionableSlope and p.shortEMASlope < -minActionableSlope:  #-- Negative trend, get out
                trendState = '--'
                if p.high < p.channelLow:  #Over sold
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy * .95, False, 2)
                elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low, possible early up
                    pass
                else:
                    if trendDuration > 2:
                        if sellPending < 5 and longPositions > 5:
                            tm.PlaceSell(ticker, targetSell, True)
                        if sellPending < 5 and longPositions > 0:
                            tm.PlaceSell(ticker, targetSell, True)
                if sellPending < 5 and longPositions > 3:
                    tm.PlaceSell(ticker, targetSell, False, 2)
                    tm.PlaceSell(ticker, targetSell, False, 2)
            elif p.longEMASlope < (
                    -1 * minActionableSlope) and p.shortEMASlope < (
                        -1 * minActionableSlope):  #-+ Bounce or early recovery
                trendState = '-+'
                if p.high < p.channelLow:  #Over sold
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy * .95, False, 2)
                elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low
                    if buyPending < 3 and longPositions < 6:
                        tm.PlaceBuy(ticker, targetBuy * .95, False, 2)
                else:
                    pass
            else:  #flat, aim for 70% long
                trendState = 'Flat'
                if p.low > p.channelHigh:  #Over Bought
                    pass
                elif p.high < p.channelLow:  #Over sold
                    if buyPending < 3 and longPositions < 8:
                        tm.PlaceBuy(ticker, targetBuy, False, 5)
                    if buyPending < 4: tm.PlaceBuy(ticker, targetBuy, False, 5)
                else:
                    pass
                if buyPending < 3 and longPositions < maxPositions:
                    tm.PlaceBuy(ticker, targetBuy, False, 5)

        tm.SetCustomValues(trendState, trendDuration)
        if trendState == prevTrendState:
            trendDuration = trendDuration + 1
        else:
            trendDuration = 0
        tm.SetCustomValues(prevTrendState, trendDuration)
Exemple #18
0
def RunPriceMomentumBlended(tickerList: list,
                            startDate: str = '1/1/1980',
                            durationInYears: int = 29,
                            stockCount: int = 9,
                            ReEvaluationInterval: int = 20,
                            longHistory: int = 365,
                            shortHistory: int = 90,
                            portfolioSize: int = 30000,
                            returndailyValues: bool = False,
                            verbose: bool = False):
    #Uses blended option for selecting stocks using three different filters
    startDate = datetime.datetime.strptime(startDate, '%m/%d/%Y')
    endDate = startDate + datetime.timedelta(days=365 * durationInYears)
    picker = StockPicker(startDate, endDate)
    for t in tickerList:
        picker.AddTicker(t)
    tm = TradingModel(modelName='PriceMomentum_Blended_longHistory_' +
                      str(longHistory) + '_shortHistory_' + str(shortHistory) +
                      '_reeval_' + str(ReEvaluationInterval) + '_stockcount_' +
                      str(stockCount) + '_filterBlended_134',
                      startingTicker='^SPX',
                      startDate=startDate,
                      durationInYears=durationInYears,
                      totalFunds=portfolioSize,
                      tranchSize=portfolioSize / stockCount,
                      verbose=verbose)
    dayCounter = 0
    if not tm.modelReady:
        print('Unable to initialize price history for PriceMomentum date ' +
              str(startDate))
        return 0
    else:
        while not tm.ModelCompleted():
            currentDate = tm.currentDate
            if dayCounter == 0:
                print('\n')
                print(currentDate)
                c, a = tm.Value()
                print(tm.modelName, int(c), int(a), int(c + a))
                print('available/buy/sell/long', tm.PositionSummary())
                tm.SellAllPositions(currentDate)
                tm.ProcessDay()
                dayCounter += 1
                shortList1 = picker.GetHighestPriceMomentum(
                    currentDate,
                    longHistoryDays=longHistory,
                    shortHistoryDays=shortHistory,
                    stocksToReturn=int(stockCount / 3),
                    filterOption=1)
                shortList2 = picker.GetHighestPriceMomentum(
                    currentDate,
                    longHistoryDays=longHistory,
                    shortHistoryDays=shortHistory,
                    stocksToReturn=int(stockCount / 3),
                    filterOption=2)
                shortList3 = picker.GetHighestPriceMomentum(
                    currentDate,
                    longHistoryDays=longHistory,
                    shortHistoryDays=shortHistory,
                    stocksToReturn=int(stockCount / 3),
                    filterOption=4)
                #shortList3 = picker.GetHighestPriceMomentum(currentDate, longHistoryDays=longHistory, shortHistoryDays=shortHistory, stocksToReturn=int(stockCount/3), filterOption=6, maxVolatility=.12)
                shortList = pd.concat([shortList1, shortList2, shortList3])
                shortList
                print(shortList)
                if len(shortList) > 0:
                    i = 0
                    ii = 0
                    while tm.TranchesAvailable() and i < 100:
                        tm.PlaceBuy(ticker=shortList.index[ii],
                                    price=1,
                                    marketOrder=True,
                                    expireAfterDays=10,
                                    verbose=verbose)
                        i += 1
                        ii += 1
                        if ii >= len(shortList): ii = 0
            tm.ProcessDay()
            dayCounter += 1
            if dayCounter >= ReEvaluationInterval: dayCounter = 0

        cv1 = tm.CloseModel(plotResults=False,
                            saveHistoryToFile=((durationInYears > 1)
                                               or verbose))
        if returndailyValues:
            return tm.GetDailyValue()
        else:
            return cv1
def RunTradingModelSwingTrend(tm: TradingModel, ticker: str):
    #Give it a date range, some money, and a stock, it will execute a strategy and return the results
    #minDeviationToTrade = .025
    minActionableSlope = 0.002
    prevTrendState, trendDuration = tm.GetCustomValues()
    if prevTrendState == None: prevTrendState = ''
    if trendDuration == None: trendDuration = 0
    p = tm.GetPriceSnapshot()
    if not p == None:
        available, buyPending, sellPending, longPositions = tm.PositionSummary(
        )
        maxPositions = available + buyPending + sellPending + longPositions
        targetBuy = p.nextDayTarget * (1 + p.fiveDayDeviation / 2)
        targetSell = p.nextDayTarget * (1 - p.fiveDayDeviation / 2)
        if p.longEMASlope >= minActionableSlope and p.shortEMASlope >= minActionableSlope:  #++	Positive trend, 70% long
            trendState = '++'
            if p.low > p.channelHigh:  #Over Bought
                if sellPending < 3 and longPositions > 7:
                    tm.PlaceSell(ticker, targetSell * (1.03), False, 10)
            elif p.low < p.channelLow:  #Still early
                if buyPending < 3 and longPositions < 6:
                    tm.PlaceBuy(ticker, targetBuy, True)
                if trendDuration > 1 and buyPending < 3:
                    tm.PlaceBuy(ticker, targetBuy, True)
            else:
                if buyPending < 3 and longPositions < 6:
                    tm.PlaceBuy(ticker, targetBuy, False)
            if buyPending < 5 and longPositions < maxPositions:
                tm.PlaceBuy(ticker, targetBuy, False)
        elif p.longEMASlope >= minActionableSlope and p.shortEMASlope < minActionableSlope:  #+- Correction or early downturn
            trendState = '+-'
            if p.low > p.channelHigh:  #Over Bought, try to get out
                if sellPending < 3 and longPositions > 7:
                    tm.PlaceSell(ticker, targetSell, False, 3)
            elif p.low < p.channelLow and p.high > p.channelLow:  #Deep correction
                if sellPending < 3 and longPositions > 7:
                    tm.PlaceSell(ticker, targetSell, False, 3)
            else:
                pass
        elif p.longEMASlope < -minActionableSlope and p.shortEMASlope < -minActionableSlope:  #-- Negative trend, aim for < 30% long
            trendState = '--'
            if p.high < p.channelLow:  #Over sold
                if buyPending < 3 and longPositions < 6:
                    tm.PlaceBuy(ticker, targetBuy * .95, False, 2)
            elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low, early down or up
                pass
            else:
                if sellPending < 5 and longPositions > 3:
                    tm.PlaceSell(ticker, targetSell, True)
                    if trendDuration > 1:
                        tm.PlaceSell(ticker, targetSell, True)
            if sellPending < 5 and longPositions > 3:
                tm.PlaceSell(ticker, targetSell, False, 2)
                tm.PlaceSell(ticker, targetSell, False, 2)
        elif p.longEMASlope < (-1 * minActionableSlope) and p.shortEMASlope < (
                -1 * minActionableSlope):  #-+ Bounce or early recovery
            trendState = '-+'
            if p.high < p.channelLow:  #Over sold
                pass
            elif p.low < p.channelLow and p.high > p.channelLow:  #Straddle Low
                if sellPending < 3 and longPositions > 3:
                    tm.PlaceSell(ticker, targetSell, False, 3)
            else:
                pass
        else:  #flat, aim for 70% long
            trendState = 'Flat'
            if p.low > p.channelHigh:  #Over Bought
                if sellPending < 3 and longPositions > 7:
                    tm.PlaceSell(ticker, targetSell * (1.03), False, 10)
            elif p.high < p.channelLow:  #Over sold
                if buyPending < 3 and longPositions < 8:
                    tm.PlaceBuy(ticker, targetBuy, False, 5)
                if buyPending < 4: tm.PlaceBuy(ticker, targetBuy, False, 5)
            else:
                pass
            if sellPending < 3 and longPositions > 7:
                tm.PlaceSell(ticker, targetSell, False, 5)
            if buyPending < 3 and longPositions < maxPositions:
                tm.PlaceBuy(ticker, targetBuy, False, 5)
        if trendState == prevTrendState:
            trendDuration = trendDuration + 1
        else:
            trendDuration = 0
        tm.SetCustomValues(prevTrendState, trendDuration)
Exemple #20
0
def RunPriceMomentum(tickerList: list,
                     startDate: str = '1/1/1982',
                     durationInYears: int = 36,
                     stockCount: int = 9,
                     ReEvaluationInterval: int = 20,
                     filterOption: int = 3,
                     longHistory: int = 365,
                     shortHistory: int = 90,
                     minPercentGain=0.05,
                     maxVolatility=.12,
                     portfolioSize: int = 30000,
                     returndailyValues: bool = False,
                     verbose: bool = False):
    #Choose the stock with the greatest long term (longHistory days) price appreciation
    #shortHistory is a shorter time frame (like 90 days) used differently by different filters
    #ReEvaluationInterval is how often to re-evaluate our choices, ideally this should be very short and not matter, otherwise the date selection is biased.
    startDate = datetime.datetime.strptime(startDate, '%m/%d/%Y')
    endDate = startDate + datetime.timedelta(days=365 * durationInYears)
    picker = StockPicker(startDate, endDate)
    for t in tickerList:
        picker.AddTicker(t)
    tm = TradingModel(modelName='PriceMomentumShort_longHistory_' +
                      str(longHistory) + '_shortHistory_' + str(shortHistory) +
                      '_reeval_' + str(ReEvaluationInterval) + '_stockcount_' +
                      str(stockCount) + '_filter' + str(filterOption) + '_' +
                      str(minPercentGain) + str(maxVolatility),
                      startingTicker='^SPX',
                      startDate=startDate,
                      durationInYears=durationInYears,
                      totalFunds=portfolioSize,
                      tranchSize=portfolioSize / stockCount,
                      verbose=verbose)
    dayCounter = 0
    if not tm.modelReady:
        print('Unable to initialize price history for PriceMomentum date ' +
              str(startDate))
        return 0
    else:
        while not tm.ModelCompleted():
            currentDate = tm.currentDate
            if dayCounter == 0:
                print('\n')
                print(currentDate)
                c, a = tm.Value()
                print(tm.modelName, int(c), int(a), int(c + a))
                print('available/buy/sell/long', tm.PositionSummary())
                tm.SellAllPositions(currentDate)
                tm.ProcessDay()
                dayCounter += 1
                shortList = picker.GetHighestPriceMomentum(
                    currentDate,
                    longHistoryDays=longHistory,
                    shortHistoryDays=shortHistory,
                    stocksToReturn=stockCount,
                    filterOption=filterOption,
                    minPercentGain=minPercentGain,
                    maxVolatility=maxVolatility)
                shortList = shortList[:stockCount]
                print(shortList)
                if len(shortList) > 0:
                    i = 0
                    ii = 0
                    while tm.TranchesAvailable(
                    ) and i < 100:  #Over long periods 100 will not be enough, 1000 would be better, but 100 also limits the impact of early gains, after a bit you are trading $300K
                        tm.PlaceBuy(ticker=shortList.index[ii],
                                    price=1,
                                    marketOrder=True,
                                    expireAfterDays=10,
                                    verbose=verbose)
                        i += 1
                        ii += 1
                        if ii >= len(shortList): ii = 0
            tm.ProcessDay()
            dayCounter += 1
            if dayCounter >= ReEvaluationInterval: dayCounter = 0

        cv1 = tm.CloseModel(plotResults=False,
                            saveHistoryToFile=((durationInYears > 1)
                                               or verbose))
        if returndailyValues:
            return tm.GetDailyValue()
        else:
            return cv1