Back to Community
Brokerage Integrations come and go, but Algos are forever (or, "This is my first/last algo, thoughts appreciated!")

Hi folks

This is obviously a live-trade algorithm, not a contest algorithm. I'm not skilled enough for that, nor do I have the time necessary to devote to get anywhere near that level. I know live-trading will be gone very, very soon (waaaaay too soon, but I'll not rehash that discussion), but this is the first algo I've come up with mostly from scratch instead of by cloning/tweaking something from someone else, and I wanted to share it before it all goes away.

The basic premise is that it taps a trend I've been seeing since the inauguration of Glorious Leader for leveraged ETFs and ETNs to spike in the first hour or two of trading, often >3%. This tries to pick it up at 2% or so and sell at 2.5%, so it's fairly high volume on day-trades which actually is an issue for me since I'm just a poor boy from a poor family and don't have the $25k+ necessary to avoid PDT flagging issues, but it might work well if you have that amount sitting around. The return was fairly high and the max DD seemed fairly reasonable for that level of return, so I wanted to share - though of course, I could easily be an idiot and have it doing something weird to produce such good returns, so if that's the case let me know and I'll swallow my embarrassment long enough to thank you.

I'm hoping that this trend will continue in the future (like I said, seems to be doing well since the inauguration, so maybe 3.5 years of good returns?), I've been tapping it the last couple of weeks as timing allows with manual trades, but I don't always have the time to sit in front of the computer and watch stocks tick, hence the dive into Q in the first place. It's set up to run on Robinhood since that's what I was using for live-trading. I set it up using what I think is a decent basket of ETFs/ETNs that can easily be adjusted if you want to.

I know a lot of the live-traders are gone or will be soon, but if there's anyone out there who wants to take a look, advice/tips/improvements/hate mail/constructive criticism would be greatly appreciated. I do intend to eventually port this and some other stuff to another platform (God only knows which one right now, but again, not the point here), and I'd love to tap the wonderful expertise I've seen on display here at Q to make this as good as the limits of its simplicity allow.

Clone Algorithm
34
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
"""
Algorithm Name:   Leveraged ETF/ETN Day-Trade spikes v1.0
Author:           Darksaber501st
Creation Date:    9/14/2017
Last Changed:     N/A
Description:      This algo attempts to generate a steady revenue stream off intraday volatility of popular 2x & 3x leveraged ETF/ETNs such as GUSH, UGAZ, XIV, UVXY, etc. It looks for a pattern I've noticed, that some of these spike 3-4% in the early trading period before eventually cooling down (or even going negative). The basic idea is that if it makes it to about 2% above open, it'll continue going to at least 3% or so, so it buys and sells fairly rapidly to try to gain about 0.5% per trade between the 2-3% marks. Anything it doesn't sell by the end of the day that is still profitable at open it dumps for what profit it does have, and it stop-losses after losing about 2% of the position value. It only buys once. It's designed for Robinhood without Gold but with obviously enough money to get around PDT flagging.

Changelog:
9/14/2017    -    Original creation
                    
"""

def initialize(context):
    """
    Called once at the start of the algorithm.
    """
    set_benchmark(sid(22009)) # SPYG
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0)) #RH Reccomended
    set_commission(commission.PerTrade(cost=0.00)) #RH Reccomended
    

    context.securities = {
        sid(40516), #XIV, Inverse Volatility
        sid(39214), #TQQQ, 3x NASDAQ
        sid(41969), #UVXY, 2x VIX Long
        sid(22009), #SPYG, SP Growth Fund
        sid(44436), #KORU, 3x Korean
        sid(42477), #UGAZ, 3x Nat Gas
        sid(42470), #DGAZ, 3x INV Nat Gas
        sid(39342), #INDL, 3x India Bull 
        sid(49073), #LABU, 3x Bull Biotech
        sid(49359), #NAIL, 3x Building Mat Bear
        sid(37852), #EDC, 3x Emerging Markets
        sid(37852), #YINN, 3x China Bull
        sid(37854), #TECL, 3x Tech Bull
        sid(49076), #DRIP, 3X Oil & Gas Bear
        sid(49077), #GUSH, 3X Oil & Gas Bull
        sid(49646), #SICK, 3X Healthcare Bear
        sid(41578), #CURE, 3X Healthcare Bull
        sid(37049), #FAS, 3x Financial Bull
        sid(50439), #CWEB, 2x China Internet Bull
        sid(39016), #LBJ, 3x Latin America Bull
        sid(49171), #UBIO, ProShares NASDAQ Biotech
        sid(39343) #UBIO, Direxion Daily Semiconductor 3x Bull
        # ... Add more here, make sure to add commas
    }
    context.dailyOpen = [0] * len(context.securities)
    context.dailyClose = [0] * len(context.securities)
    context.dailyHigh = [0] * len(context.securities)
    context.dailyLow = [0] * len(context.securities)
    context.dailyHighTime = [0] * len(context.securities)
    context.dailyLowTime = [0] * len(context.securities)
    
    context.running = False
    
    context.stops = [False] * len(context.securities)
    context.boughtToday = [False] * len(context.securities)
    context.soldToday = [False] * len(context.securities)
    
    schedule_function(at_BOD, date_rules.every_day(), time_rules.market_open(minutes=1))
    schedule_function(at_EOD, date_rules.every_day(), time_rules.market_close(minutes=1))

def before_trading_start(context, data):
    c = context
    c.running = False

    i = -1
    for security in context.securities:
        i = i+1
        c.dailyHigh[i] = 0
        c.dailyHighTime[i] = -1
        c.dailyLow[i] = 1000000
        c.dailyLowTime[i] = -1
        c.boughtToday[i] = False
        c.soldToday[i] = False
        c.stops[i] = False
        
def at_BOD(context, data):
    c = context
    i = -1
    for security in context.securities:
        i = i+1
        c.dailyOpen[i] = data.current(security,'price')
        if context.portfolio.positions[security].amount>0 and context.portfolio.positions[security].cost_basis < data.current(security,'price'):
            order_target_percent(security,0) #<issed our goal, take what profits we can
            c.boughtToday[i] = True
            c.soldToday[i] = True
            
    c.running = True

def at_EOD(context, data):
    c = context
    c.running = False
    i = -1
    for security in context.securities:
        i = i+1
        c.dailyClose[i] = data.current(security,'price')
        log.info(';EOD printout Open/Close/High/HighTime/Low/LowTime;{};{};{};{};{};{};{}'.format(security,c.dailyOpen[i],c.dailyClose[i],c.dailyHigh[i],c.dailyHighTime[i],c.dailyLow[i],c.dailyLowTime[i]))
        
        
        if len(get_open_orders(security)) > 0:
            cancel_open_orders_for(context,data,security)
            
        
def cancel_open_orders_for(context, data, security):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            if stock is security:
                cancel_order(order)
        
def handle_data(context,data):
    c = context
    i = -1
    if c.running == True:
        for security in context.securities:
            i = i+1
            curPrice = data.current(security,'price')
            if curPrice > c.dailyHigh[i]:
                c.dailyHigh[i] = curPrice
                c.dailyHighTime[i] = get_datetime('US/Eastern') 

            if curPrice < c.dailyLow[i]:
                c.dailyLow[i] = curPrice
                c.dailyLowTime[i] = get_datetime('US/Eastern')
                
            if context.portfolio.positions[security].amount>0 and context.portfolio.positions[security].cost_basis*0.98 > curPrice and c.stops[i]==False:
                cancel_open_orders_for(context,data,security)
                order_target_percent(security,0) # Stop-loss, eat it
                log.info(';stop-loss on;{}'.format(security))
                c.stops[i]=True #Don't buy again today
            

            if c.boughtToday[i] == False and curPrice > c.dailyOpen[i]*1.02 and c.stops[i]==False:
                log.info(';hit 2%, buying;{};{};{},{}'.format(security,get_datetime('US/Eastern'),curPrice,c.dailyOpen[i]))
                c.boughtToday[i] = True
                if len(get_open_orders(security)) == 0 and c.stops[i]==False and context.portfolio.positions[security].amount == 0:
                    cancel_open_orders_for(context,data,security)
                    order_target_percent(security,0.9)
                    
            if c.boughtToday[i] == True and c.soldToday[i] == False and curPrice > context.portfolio.positions[security].cost_basis*1.005 and len(get_open_orders(security)) == 0 and context.portfolio.positions[security].amount > 0:
                c.soldToday[i] = True
                c.soldSingleToday = True
                log.info(';hit 0.5% profit, limit selling;{};{};{}'.format(security,get_datetime('US/Eastern'),context.portfolio.positions[security].cost_basis*1.005))
                if len(get_open_orders(security)) > 0:
                    cancel_open_orders_for(context,data,security)
                order_target_percent(security,0,style=LimitOrder(context.portfolio.positions[security].cost_basis*1.005)) #Take profit
There was a runtime error.
3 responses

Hi. I see this algo works well since the year 2016, but before it has not a good profit. Is there any reason for it?

I'm guessing that a lot of it has to do with the nature of these leveraged ETF/ETNs. A lot of them have lost a LOT of value since their inception (some, like UVXY, are frankly defective), but they've all stabilized at a price point people were willing to play around with over the last year or so. Take GUSH as an example, it's one of the securities that most clearly displays the trend I'm trying to capitalize on. It's inception date is May 28, 2015. It wasn't even around much before 2016, and prior to 2016 it lost about 2/3 of its value since it wasn't being heavily traded. When the volume started to pick up, the price stabilized, and it's behaved normally since. It's only in the last year that its daily trading volume has exceeded 1M.

In short, these sucked while they were in diapers and were learning to crawl. Now that they're walking normally, they're doing great.

Made a lot of different tweaks to avoid issues with margin, over-ordering, etc. Did a really basic sensitivity analysis to try and maximize returns based on some of the key thresholds used in the algo. Also, significantly altered the basket of securities to try and minimize the number of stops.

Lower DD, lower returns, much lower beta. I think still fairly good for a beginner.

Clone Algorithm
29
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
"""
Algorithm Name:   Leveraged ETF/ETN Day-Trade spikes v1.2
Author:           Darksaber501st
Creation Date:    9/14/2017
Last Changed:     9/26/2017
Description:      
This algo attempts to generate a steady revenue stream off intraday volatility of popular 2x & 3x leveraged ETF/ETNs.
Examples include GUSH, UGAZ, XIV, UVXY, etc. 
It looks for a pattern I've noticed, that some of these spike 3-4% in the early trading period before eventually cooling down (or even going negative). 
The basic idea is that if it makes it to about 1-2% above open, it'll continue going to at least 3% or so.
Therefore, it buys and sells fairly rapidly to try to gain about 0.5-1% per trade between the 2-3% marks (depending on how global variables are set). 
Anything it doesn't sell by the end of the day that is still profitable at open it dumps for what profit it does have. 
Stop-losses after losing about 2% of the position value. 
It only buys a stock once per day. 
It's designed for Robinhood without Gold but with obviously enough money to get around PDT flagging.

TarPer function borrowed from Charles Witt's VIX work.

Changelog:
9/14/2017   -   Original creation
9/17/2017   -   Added some additional logging
                Added the TarPer function, taken from Charles Witt's VIX work. 
                Added some additional ETFs/ETNs to the security basket. More to come.
                Fixed issue with over-ordering
9/25/2017	-   Updated basket to only use stocks producing least amount of stop-loss
9/26/2017   -   Sensitivity analysis to maximize returns

                    
"""
# Global Variables for use in paramterized analysis
inputThresholdForBuying = 1.015 #x% of open, as decimal.
inputStopLossLevel = 0.98 #x% of cost basis, as decimal.
inputTakeProfitLevel = 1.015 #x% of cost basis, as decimal.
inputTargetPercentLevel = 0.90 #x% of available cash to try and use. Higher = greater risk, greater returns
inputFullBasket = False

def initialize(context):
    set_benchmark(sid(22009)) # SPYG a good benchmark for the 2017 period
    set_slippage(slippage.VolumeShareSlippage(volume_limit=.20, price_impact=0.0)) #RH Reccomended
    set_commission(commission.PerTrade(cost=0.00)) #RH Reccomended
    
    # Global Variables
    context.thresholdForBuying = inputThresholdForBuying #x% of open, as decimal. 1.01 to 1.02 reccomended
    context.stopLossLevel = inputStopLossLevel #x% of cost basis, as decimal. Tested at 0.98
    context.takeProfitLevel = inputTakeProfitLevel #x% of cost basis, as decimal. 1.005 to 1.01 reccommended
    context.targetPercentLevel = inputTargetPercentLevel #x% of available cash to try and use. Higher = greater risk, greater returns
    context.fullBasket = inputFullBasket
    """
    # Global Variables
    context.thresholdForBuying = 1.015 #x% of open, as decimal. 1.01 to 1.02 reccomended
    context.stopLossLevel = 0.98 #x% of cost basis, as decimal. Tested at 0.98
    context.takeProfitLevel = 1.01 #x% of cost basis, as decimal. 1.005 to 1.01 reccommended
    context.targetPercentLevel = 0.9 #x% of available cash to try and use. Higher = greater risk, greater returns
    context.fullBasket = True
    """
    if context.fullBasket == False:
        #"""
        # Lowest % Causing stop-loss
        context.securities = {
            # Best to least best
            sid(37852), #EDC, 3x Emerging Markets BULL
            sid(41578), #CURE, 3X Healthcare Bull
            sid(37854), #TECL, 3x Tech Bull
            sid(39214), #TQQQ, 3x NASDAQ-100 Bull Proshares
            sid(39211), #SQQQ, 3x NASDAQ-100 Bear Proshares
            sid(39215), #UDOW, 3x Dow Bull Proshares
            sid(38596), #DRN, 3x MCSI Real Estate Bull
            sid(39342), #INDL, 3x India Bull
            sid(37044), #ERY, 3X Energy Bear
            sid(37049), #FAS, 3x Financial Bull
            sid(37048), #FAZ, 3x Financial Bear
            sid(49077), #GUSH, 3X Oil & Gas Bull
            sid(39343), #SOXL, 3x Semiconductor Bull
            sid(39016), #LBJ, 3x Latin America Bull
            sid(49171), #UBIO, 3x Biotech Bull Proshares
            sid(39344), #SOXS, 3x Semiconductor Bear
            # ... Add more here, make sure to add commas
        }
    else:
        # === WHOLE LIST OF AVAILABLE LEVERAGED ETFS ===
        context.securities = {
            # Direxion
            sid(39898), #GASL, 3x Nat Gas
            sid(49639), #GASX, 3x INV Nat Gas
            sid(49076), #DRIP, 3X Oil & Gas Bear
            sid(49077), #GUSH, 3X Oil & Gas Bull
            sid(37854), #TECL, 3x Tech Bull
            sid(37857), #TECS, 3x Tech Bear
            sid(37514), #SPXL, 3X S&P Bull
            sid(37083), #SPXS, 3X S&P Bear
            sid(37513), #ERX, 3X Energy Bull
            sid(37044), #ERX, 3X Energy Bear
            sid(40553), #NUGT, 3X Gold Miners Bull
            sid(40554), #DUST, 3X Gold Miners Bear
            sid(37049), #FAS, 3x Financial Bull
            sid(37048), #FAZ, 3x Financial Bear
            sid(41578), #CURE, 3X Healthcare Bull
            sid(49646), #SICK, 3X Healthcare Bear
            sid(49359), #NAIL, 3x Homebuilders & Supplies Bull
            sid(49350), #CLAW, 3x Homebuilders & Supplies Bear
            sid(39343), #SOXL, 3x Semiconductor Bull
            sid(39344), #SOXS, 3x Semiconductor Bear
            sid(38596), #DRN, 3x MCSI Real Estate Bull
            sid(38597), #DRV, 3x MCSI Real Estate Bear
            sid(50837), #DFEN, 3x Aerospace & Defense Bull
            sid(37852), #EDC, 3x Emerging Markets BULL
            sid(37855), #EDZ, 3x Emerging Markets BEAR
            sid(44436), #KORU, 3x Korean Bull
            sid(39342), #INDL, 3x India Bull 
            sid(49137), #CHAD, 1x China Bear
            sid(39017), #YINN, 3x FTSE China BULL
            sid(39015), #YANG, 3x FTSE China Bear
            sid(39016), #LBJ, 3x Latin America Bull

            # Other - Non-sector specific
            sid(22009), #SPYG, SP Growth Fund
            sid(38533), #UPRO, 3x S&P 500 Bull Proshares
            sid(38532), #SPXU, 3x S&P 500 Bear Proshares
            sid(39215), #UDOW, 3x Dow Bull Proshares
            sid(39212), #SDOW, 3x Dow Bear Proshares
            sid(39214), #TQQQ, 3x NASDAQ-100 Bull Proshares
            sid(39211), #SQQQ, 3x NASDAQ-100 Bear Proshares
            sid(40512), #VIIX, Short-Term Bull (Increased) Volatility, VelocityShares
            sid(40516), #XIV,  Short-Term Bear (Decreased) Volatility, VelocityShares
            sid(41969), #UVXY, 2x Sgirt-Term Bull (Increased) Volatility, Proshares
            sid(40515), #TVIX, 2x Short-Term Bull (Increased) Volatility, VelocityShares

            # Other - sector specific
            sid(42477), #UGAZ, 3x Nat Gas Bull VelocityShares 
            sid(42470), #DGAZ, 3x Nat Gas Bear VelocityShares 
            sid(49171), #UBIO, 3x Biotech Bull Proshares
            sid(49173), #ZBIO, 3x Biotech Bear Proshares
            # ... Add more here, make sure to add commas
        }

    # Internal Variables
    context.dailyOpen = [0] * len(context.securities)
    context.dailyClose = [0] * len(context.securities)
    context.dailyHigh = [0] * len(context.securities)
    context.dailyLow = [0] * len(context.securities)
    context.dailyHighTime = [0] * len(context.securities)
    context.dailyLowTime = [0] * len(context.securities)
    context.prevDayValue = 0
    context.operatingDays = 0

    context.running = False
    context.cashFlag = False

    context.openOrder = [False] * len(context.securities)
    context.stops = [False] * len(context.securities)
    context.boughtToday = [False] * len(context.securities)
    context.soldToday = [False] * len(context.securities)
    
    schedule_function(at_BOD, date_rules.every_day(), time_rules.market_open(minutes=1))
    schedule_function(at_EOD, date_rules.every_day(), time_rules.market_close(minutes=1))

def handle_data(context,data):
    c = context
    i = -1
    
    if context.portfolio.cash < 0 and c.cashFlag == False:
        log.error("Cash < 0")
        c.cashFlag = True #Don't repeat today
    
    if c.running == True:
        for security in context.securities:
            i = i+1
            curPrice = data.current(security,'price')

            # Update highs/lows
            if curPrice > c.dailyHigh[i]:
                c.dailyHigh[i] = curPrice
                c.dailyHighTime[i] = get_datetime('US/Eastern') 

            if curPrice < c.dailyLow[i]:
                c.dailyLow[i] = curPrice
                c.dailyLowTime[i] = get_datetime('US/Eastern')
                
            if context.portfolio.positions[security].amount>0 and context.portfolio.positions[security].cost_basis*c.stopLossLevel > curPrice and c.stops[i]==False:
                cancel_open_orders_for(context,data,security)
                log.info(';hit {}% of cost basis, triggered stop-loss on - security;{}'.format(c.stopLossLevel*100,security))
                order_target_percent(security,0)
                c.stops[i]=True #Don't buy again today
            

            if c.boughtToday[i] == False and curPrice > c.dailyOpen[i]*c.thresholdForBuying:
                if c.stops[i]==False and context.portfolio.positions[security].amount == 0:
                    if check_open_orders_for(context,data,security) == False and len(get_open_orders())==0 and context.portfolio.positions_value == 0:
                        c.boughtToday[i] = True
                        log.info(';hit {}%, buying - security/open/current price;{};{},{}'.format((c.thresholdForBuying-1)*100,security,c.dailyOpen[i],curPrice))
                        cancel_open_orders_for(context,data,security)
                        TarPer(context,data,security,c.targetPercentLevel)

            if c.boughtToday[i] == True and c.soldToday[i] == False and curPrice > context.portfolio.positions[security].cost_basis*c.takeProfitLevel and check_open_orders_for(context,data,security) == False and context.portfolio.positions[security].amount > 0:
                c.soldToday[i] = True
                log.info(';hit {}% profit, limit selling - security/costbasis/sell threshold;{};{};{}'.format((c.takeProfitLevel-1)*100,security,context.portfolio.positions[security].cost_basis,context.portfolio.positions[security].cost_basis*c.takeProfitLevel))
                order_target_percent(security,0,style=LimitOrder(context.portfolio.positions[security].cost_basis*c.takeProfitLevel)) #Take profit
                
def before_trading_start(context, data):
    c = context
    c.running = False
    c.cashFlag = False

    i = -1
    for security in context.securities:
        i = i+1
        c.dailyHigh[i] = 0
        c.dailyHighTime[i] = -1
        c.dailyLow[i] = 1000000
        c.dailyLowTime[i] = -1
        c.boughtToday[i] = False
        c.soldToday[i] = False
        c.stops[i] = False
        
def at_BOD(context, data):
    c = context
    i = -1
    for security in context.securities:
        i = i+1
        c.dailyOpen[i] = data.current(security,'price')
        if context.portfolio.positions[security].amount>0 and context.portfolio.positions[security].cost_basis < data.current(security,'price'):
            log.info(';did not hit targeted profit, selling at open for what we can get - security/cost basis/open;{}'.format(security,context.portfolio.positions[security].cost_basis,c.dailyOpen[i]))
            order_target_percent(security,0) #<issed our goal, take what profits we can
            c.boughtToday[i] = True
            c.soldToday[i] = True
            
    c.running = True

def at_EOD(context, data):
    c = context
    c.running = False
    c.operatingDays = c.operatingDays+1
    i = -1
    for security in context.securities:
        i = i+1
        c.dailyClose[i] = data.current(security,'price')
        
        if c.soldToday[i] == True or c.boughtToday[i] == True:
            log.info(';EOD printout for a stock traded today - Open/Close/High/HighTime/Low/LowTime;{};{};{};{};{};{};{}'.format(security,c.dailyOpen[i],c.dailyClose[i],c.dailyHigh[i],c.dailyHighTime[i],c.dailyLow[i],c.dailyLowTime[i]))
        
        
        if len(get_open_orders(security)) > 0:
            cancel_open_orders_for(context,data,security)
            
def return_cash_to_trading_pool(context, data, returnedCash):
    context.dailyTradeableCash = context.dailyTradeableCash + returnedCash    
            
def check_open_orders_for(context, data, security):
    oo = get_open_orders()
    finalResult = False
    if len(oo) == 0:
        finalResult = False # Complete
    else:
        for stock, orders in oo.iteritems():
            for order in orders:
                if stock is security:
                    finalResult = True # Still processing
    
    return finalResult
            
def cancel_open_orders_for(context, data, security):
    oo = get_open_orders()
    if len(oo) == 0:
        return
    for stock, orders in oo.iteritems():
        for order in orders:
            if stock is security:
                cancel_order(order)

def TarPer(context, data, security, TargetPercent):
    c = context
    if data.can_trade(security):

        if 0 == TargetPercent:
            log.info(';Selling all shares - security;{}'.format(security))
            order_target_percent(security, 0.00)
        else:
            AvailableCash = c.portfolio.cash #Use cash only to avoid issues with trading leveraged ETFs on margin
            amount = c.portfolio.positions[security].amount
            price = data.current(security, 'price')
            PosValue   = float(amount * price)
            TarValue   = float(AvailableCash * TargetPercent)
            DiffValue  = float(TarValue - PosValue)
            DiffAmount = int(DiffValue / price)
            DiffAmount = 0 if 0 > DiffAmount and 0 == amount else DiffAmount
            log.info(';TarPer Selling/Buying - security/number of shares;{};{}'.format(security,DiffAmount))
            order(security, DiffAmount)
        
There was a runtime error.