Code Monkey home page Code Monkey logo

trading-stocks's People

Contributors

yasmanyarciacorcho avatar

Watchers

 avatar

trading-stocks's Issues

Test the Limit order to execute the exits

Strategy: vwap v0.0.0.7

Right now we are using a market order to enter a trade and a liquidate to exit from the trade. We are experimenting some numerical differences on our expected exit from the trades.

We would like to test the performance of the swap strategy by sending a limit order to sell just after realizing a market order to buy.
The limit order should be based on the price returned from the market order ticket and our limit order's current risk.

GAP NOT WORKING PROPERLY

When adding Gap Percentage to line 212 algo is not calculating the gap. Make trades on gap lower than the percentage and is not liquidating, and I think does not liquidate until next gap(need to test this)

Average True Range (ATR)

The average true range (ATR) is a technical analysis indicator. This indicator will tell us if is a good trade to enter base on Profit exit. Example if the ATR of Symbol (SPY) averegae 1.30 we need to calculate the percentage that had moved and and make a trade if the parameter is between -24% to +24% (-0.31 to +0.31)

The first step in calculating ATR is to find a series of true range values for a security. The price range of an asset for a given trading day is simply its high minus its low. https://www.investopedia.com/terms/a/atr.asp

Update the source code to use the symbol string value

Current behavior

Currently, we are using the full definition of symbol to store the trading equity information. In many cases around the code, this could be improved to use just the string value of the symbol.

Desired behavior
Use just the symbol string value to try to optimize the code performance and memory requirements.

Separate for consolidate time Line 36,37,38 for strategy

Separate per strategy

Region - General configurations

    # All the variables that manages times are written in seconds.
    self.ConsolidateSecondsTime = 60               # Define the one min candle.
    self.ConsolidateLowPriceTime = 60         # Define low price candle, used on vwap strategy.
    self.AccumulatePositiveTimeRan = 0     # Interval time when all equity price should be over the vwap before entering in a buy trade.

Limit amount trade per symbol per day

Parameter to limit how many trades is allow to enter for each symbol.

Note: We need to consider in other version to allow to trade while is winning. Example if a symbol wins allow another trade until have a losing trade.

Adding Volume Indicator

Relative Volume (often times called RVOL) or
"Performance by Relative Volatility (TR/ATR)"https://blog.tradervue.com/2015/03/04/new-relative-volatility-report/

What is Relative Volume?
Relative Volume (often times called RVOL) is an indicator that tells traders how current trading volume is compared to past trading volume over a given period.

It is kind of a like a radar for how “in-play” a stock is.

The higher the relative volume is the more in play it is because more traders are watching and trading it.

As traders, this is what we want.

Stocks that have a lot of volume have more liquidity and tend to trade better than stocks with low relative volume.

The RVOL is displayed as a ratio.

So if it is showing 3.5 relative volume, that means it is trading at 3.5 times its normal volume for that time period.

As day traders we like to see RVOL at 2 or higher with a positive catalyst, low float and ideally a higher short interest.

When all this falls in line together we have a recipe for parabolic moves that can make trading months and sometimes even years.

This is also a good metric to watch for potential bottoming or topping in stocks.

As a stock gets oversold or overbought we want to look for volume to get a spike in relative volume which would indicate that buyers and seller are fighting over an important support or resistance level and will likely reverse.

No trade while Inside Day

What is an inside day?
You need two bars to define an inside day. The reason for this is obvious when you learn that an inside day is when the low is higher than yesterday’s low and today’s high is lower than yesterday’s high. If both conditions are fulfilled, you have an inside day.

In other words, all price action of an inside day is inside the price action of yesterday. The whole range falls inside the range of yesterday. This chart of the oil futures reveals plenty of inside days (green arrows – ignore the red arrows):

Inside day in trading
Inside day in trading
As you can see, the bars over the green arrows show an inside day and they are quite frequent, but it varies from market to market. It depends on the volatility and the price action between the close and the opening the next day. The above chart is crude oil and this market has many inside days.
image

algo not trading everyday

Sample from 1/1/21 to 1/31/21. Algo did not trade on 1/6. When try 1/6 alone it trade. Need to test more

Strategy enter to buy 2nd minute candle

Should enter to buy only if second candle (9:31:00 - 9:31:59 ) brakes the high of the first candle.
-Stop Loss low of the first minute candle (see picture)
-Win the same risk ( what we have done already)

i
image

Gap Issue

Gap works, but if position is open won't closed until another gap

GAP PERCENTAG - TRADE REMAINS OPEN UNTIL NEXT GAP PERCENTAGE

TRADE RENMAINS OPEN UNTIL NEXT GAP OF 2%, TO REPLICATE THIS ISSUE TRY

PARAMETER GAP 2 LINE 212
THIS IS THE CODE I USED, I CHANGE
"self.ConsolidateSecondsTime = 60 * 5 # Define the one min candle."
" trading_equity.LastEntryExitOnWinPrice = (trading_equity.LastEntryPrice + (trading_equity.LastEntryPrice - trading_equity.LastEntryExitOnLostPrice)*2)"

CODE ------------

#region imports
from hashlib import new
from AlgorithmImports import *
import enum
#endregion

class LiquidateState(enum.Enum):
Normal = 1 # It is not mandatory to liquidate.
ToWin = 2 # It is mandatory to liquidate if there is a win or there is not a loss. Equity current price >= entry price.
Force = 3 # Liquidate the equity now.

class VWAPStrategy(QCAlgorithm):

def Initialize(self):
    #Region - Initialize cash flow
    self.SetStartDate(2021, 1, 1)   # Set Start Date.
    self.SetEndDate(2021, 12, 31)    # Set End Date.
    self.SetCash(1000000)            # Set Strategy Cash.

    self.stocksTrading = QCStocksTrading(self)

    # Region - Initialize trading equities
    ## One equity should be traded at least.
    equities_symbols = ["aapl", "spy", "tsla", "msft", "ba", "qqq", "fb", "pypl", "twtr", "nvda", "amd", "c", "baba", "bac", "gld", "tgt", "wmt", "amzn", "googl" ]

    for symbol in equities_symbols:
        equity = self.AddEquity(symbol, Resolution.Second)
        self.stocksTrading.AddEquity(equity)

    # Region - Set Broker configurations
    self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin)
    
    # Region - General configurations
    # All the variables that manages times are written in seconds.
    self.ConsolidateSecondsTime = 60 * 5    # Define the one min candle.
    self.ConsolidateLowPriceTime = 60 * 5   # Define low price candle, used on vwap strategy.
    self.AccumulatePositiveTimeRan = 0      # Interval time when all equity price should be over the vwap before entering in a buy trade.
    
    self.IsAllowToTradeByTime = False

    self.CurrentTradingDay = -1

    self.LiquidateState = LiquidateState.Normal

    ## Sub region - Schedule events
    self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen(equities_symbols[0], 2), self.ResetDataAfterMarketOpenHandler)
    self.endTimeToTradeBeforeMarketClose = 300
    self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose(equities_symbols[0], self.endTimeToTradeBeforeMarketClose), self.BeforeMarketCloseHandler)
    self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose(equities_symbols[0], self.endTimeToTradeBeforeMarketClose + 10), self.BeforeMarketCloseTryToLiquidateOnWinStateHandler)
    self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose(equities_symbols[0], self.endTimeToTradeBeforeMarketClose + 5), self.BeforeMarketCloseLiquidateOnDayStateHandler)
    
    # Risk management
    self.RiskPerTrade = 200

    # Region - Configuration per symbol
    for trading_equity in self.stocksTrading.GetTradingEquities():
        symbol = trading_equity.Symbol()
        # Indicators
        # QuantConnect indicators has a field 'name' which returns the indicator name.
        self.stocksTrading.RegisterIndicatorForEquity(symbol, 'vwap', self.VWAP(symbol))     # Maybe we can test if it is a good fit for us. Example vwap.Name

        self.Consolidate(symbol, timedelta(seconds=self.ConsolidateSecondsTime), self.MinuteConsolidateHandler)
        self.Consolidate(symbol, timedelta(seconds=self.ConsolidateLowPriceTime), self.LowConsolidateHandler)

def OnData(self, data):
    for trading_equity in self.stocksTrading.GetTradingEquities():
        symbol = trading_equity.Symbol()
        if not data.Bars.ContainsKey(symbol):
            return

        equity_current_price = data.Bars[symbol].Price

        if self.CurrentTradingDay != self.Time.day:
            self.UpdateOpenPriceAfterMarketOpenHandler(trading_equity, equity_current_price)
            self.CurrentTradingDay = self.Time.day

        if self.ShouldIgnoreOnDataEvent(trading_equity, data):
            return

        self.UpdateLastBrokenCandle(trading_equity)

        # Liquidate by time
        if (self.ShouldLiquidateToWin(trading_equity, equity_current_price) 
            or self.ShouldForceLiquidate()):
            self.Liquidate(symbol)
            return

        if not self.LiquidateState is LiquidateState.Normal:
            return

        if (not self.Portfolio[symbol].Invested 
            and self.ShouldEnterToBuy(trading_equity, equity_current_price)):
                trading_equity.LastEntryPrice = equity_current_price
                trading_equity.LastEntryExitOnLostPrice = trading_equity.LowPriceWindow[0].Low
                trading_equity.LastEntryExitOnWinPrice = (trading_equity.LastEntryPrice + (trading_equity.LastEntryPrice - trading_equity.LastEntryExitOnLostPrice)*2)
                denominator = trading_equity.LastEntryPrice - trading_equity.LastEntryExitOnLostPrice
                if denominator == 0:
                    return
                count_actions_to_buy = int(self.RiskPerTrade / denominator)
                self.MarketOrder(symbol, count_actions_to_buy)
                trading_equity.SetLastTradeTime(self.Time)
        elif self.Portfolio[symbol].Invested:
            if (trading_equity.LastEntryExitOnLostPrice > equity_current_price or
                trading_equity.LastEntryExitOnWinPrice <= equity_current_price):
                self.Liquidate(symbol)
                trading_equity.SetLastTradeTime(self.Time)

# Eval when we shouldn't make a trade. This block specify when to trade or not to trade.
def ShouldIgnoreOnDataEvent(self, trading_equity, data):
    if not trading_equity.IsAllowToTradeByGapPercent:
        return True
    if not self.IsAllowToTradeByTime:
        return True
    vwap = trading_equity.GetIndicator('vwap')
    if ((not vwap is None and
        not vwap.IsReady) or
        not trading_equity.CurrentTradingWindow.IsReady or
        not trading_equity.LowPriceWindow.IsReady):
        return True
    if (self.Time - trading_equity.LastTradeTime).total_seconds() < self.ConsolidateSecondsTime:
        return True
    return False

def UpdateOpenPriceAfterMarketOpenHandler(self, trading_equity, equity_open_day_price):
    if trading_equity.LastDayClosePrice is None:
        return
    gapPercent = self.CalculateMarketGapPercent(trading_equity.LastDayClosePrice, equity_open_day_price)
    trading_equity.IsAllowToTradeByGapPercent = gapPercent > trading_equity.DefaultGapPercentAllowToTrade # add percent per gap. if gapPercent < 2 => means if gap percent is less than 2 percent.

# Region After Market Open
def ResetDataAfterMarketOpenHandler(self):
    self.IsAllowToTradeByTime = True
    self.LiquidateState = LiquidateState.Normal
    for equity in self.stocksTrading.GetTradingEquities():
        equity.CurrentTradingWindow = RollingWindow[TradeBar](2)
# EndRegion

# Region - Before market close.
def BeforeMarketCloseHandler(self):
    self.IsAllowToTradeByTime = False
    for equity in self.stocksTrading.GetTradingEquities():
        equity.LastDayClosePrice = self.Securities[equity.Symbol()].Price

def BeforeMarketCloseTryToLiquidateOnWinStateHandler(self):
    self.LiquidateState = LiquidateState.ToWin

def BeforeMarketCloseLiquidateOnDayStateHandler(self):
    self.LiquidateState = LiquidateState.Force
# EndRegion

# Region Consolidates, update rolling windows
def MinuteConsolidateHandler(self, trade_bar):
    equity = self.stocksTrading.GetEquity(trade_bar.Symbol)
    self.Log(trade_bar.Symbol)
    if not equity is None:
        equity.CurrentTradingWindow.Add(trade_bar)

def LowConsolidateHandler(self, trade_bar):
    equity = self.stocksTrading.GetEquity(trade_bar.Symbol)
    if not equity is None:
        equity.LowPriceWindow.Add(trade_bar)
# EndRegion

def ShouldLiquidateToWin(self, trading_equity, equity_current_price):
    if (self.LiquidateState is LiquidateState.ToWin
        and self.Portfolio[trading_equity.Symbol()].Invested
        and trading_equity.LastEntryPrice <= equity_current_price):
        return True
    return False

def ShouldForceLiquidate(self):
    if (self.LiquidateState is LiquidateState.Force
        and self.Portfolio.Invested):
        return True
    return False

# 1 - Enter to buy when the previous candle High price is greater than VWAP current value  
#     and its Low price is lower than VWAP current value and the same time
# 2 - The equity current price is greater than the previous candle high value.
def ShouldEnterToBuy(self, trading_equity, equity_current_price):
    vwap = trading_equity.GetIndicator('vwap')
    return (not trading_equity.LastBrokenCandle is None
            and self.IsPositiveBrokenCandle(vwap, trading_equity)
            and (trading_equity.CurrentTradingWindow[0].Time - trading_equity.LastBrokenCandle.Time).total_seconds() >= self.AccumulatePositiveTimeRan
            and equity_current_price > trading_equity.CurrentTradingWindow[0].High) 

def IsPositiveBrokenCandle(self, vwap, trading_equity):
    candle = trading_equity.CurrentTradingWindow[0]
    return (not vwap is None 
        and (candle.Low < vwap.Current.Value         
        and candle.Close >= vwap.Current.Value))

def UpdateLastBrokenCandle(self, trading_equity):
    current_trading_window = trading_equity.CurrentTradingWindow[0]
    vwap = trading_equity.GetIndicator('vwap')
    if vwap is None:
        return
    if (not trading_equity.LastBrokenCandle is None 
        and current_trading_window.Low < vwap.Current.Value):
        trading_equity.LastBrokenCandle = None
    if (trading_equity.LastBrokenCandle is None
        and self.IsPositiveBrokenCandle(vwap, trading_equity)):
        trading_equity.LastBrokenCandle = current_trading_window

def CalculateMarketGapPercent(self, last_close_day_price, current_day_open_price):
    return (current_day_open_price - last_close_day_price) / current_day_open_price * 100

So far, all prices are based in USD dollar for any field.

self.LastEntryPrice = 1 <=> self.LastEntryPrice = 1 USD

class EquityTradeModel:
def init(self, symbol, equity, default_gap_percent_to_trade = 2):
self.__symbol = symbol
self.__equity = equity

    self.indicators = {}

    self.LastEntryPrice = None
    self.LastEntryExitOnLostPrice = None
    self.LastEntryExitOnWinPrice = None
    self.LastDayClosePrice = None

    self.LastTradeTime = None

    self.IsAllowToTradeByGapPercent = True
    self.DefaultGapPercentAllowToTrade = default_gap_percent_to_trade

    self.LastBrokenCandle = None
    self.CurrentTradingWindow = None
    self.LowPriceWindow = None

def Symbol(self):
    return self.__symbol

def Equity(self):
    return self.__equity

# Return True if the indicator registered
def RegisterIndicator(self, indicator_name, indicator):
    if not indicator_name in self.indicators:
        self.indicators[indicator_name] = indicator
        return True
    return False

# Return True if the indicator unregistered
def UnRegisterIndicator(self, indicator_name):
    if indicator_name in self.indicators:
        del self.indicators[indicator_name]
        return True
    return False

def SetLastTradeTime(self, time):
    self.LastTradeTime = time

def ResetEquityLastTradeTime(self):
    self.SetLastTradeTime(None)

def GetIndicator(self, indicator_name):
    if indicator_name in self.indicators:
        return self.indicators[indicator_name]
    return None

class QCEquityTradeModel(EquityTradeModel):
def init(self, equity):
EquityTradeModel.init(self, equity.Symbol, equity)

    self.LastBrokenCandle = None
    self.CurrentTradingWindow = RollingWindow[TradeBar](2)
    self.LowPriceWindow = RollingWindow[TradeBar](1)

    def ResetEquityLastTradeTime(self, qc_algorithm):
        self.SetLastTradeTime(qc_algorithm.Time)

class StocksTrading:
def init(self):
self.equities = {}

# return True if the equity was added correctly.
def AddEquity(self, equity_symbol, equity):
    if equity_symbol is self.__equitie:
        return False
    self.equities[equity_symbol] = EquityTradeModel(equity_symbol, equity)
    return True

# Return True if the equity was removed correctly.
def RemoveEquity(self, equity_symbol):
    del self.equities[equity_symbol]

# Return True if the indicator was registered for the equity
def RegisterIndicatorForEquity(self, equity_symbol, indicator_name, indicator):
    if equity_symbol in self.equities:
        return self.equities[equity_symbol].RegisterIndicator(indicator_name, indicator)
    return False

# Return True if the indicator was unregistered from the equity
def UnRegisterIndicatorForEquity(self, equity_symbol, indicator_name):
    if equity_symbol in self.equities:
        return self.equities[equity_symbol].UnRegisterIndicator(indicator_name)
    return False

# Return the list of symbols that currently are being trading
def GetEquitiesTradingSymbols(self):
    return self.equities.keys()

def GetTradingEquities(self):
    return self.equities.values()

# Return amount of trading.
def TotalStocksBeingTrading(self):
    return len(self.equities)

def IsEquityBeingTrading(self, symbol):
    return symbol in self.equities

# Return EquityTradeModel of the parameter 'symbol'
def GetEquity(self, symbol):
    if self.IsEquityBeingTrading(symbol):
        return self.equities[symbol]
    return None

class QCStocksTrading(StocksTrading):
def init(self, qcAlgorithm):
StocksTrading.init(self)
self.__qcAlgorithm = qcAlgorithm

def AddEquity(self, equity):
    if not self.GetEquity(equity.Symbol) is None:
        return False

    equity.SetDataNormalizationMode(DataNormalizationMode.Raw)

    qc_equity_model = self.equities[equity.Symbol] = QCEquityTradeModel(equity)
    qc_equity_model.LastTradeTime = self.__qcAlgorithm.Time

def RegisterIndicatorForEquity(self, equity_symbol, indicator):
    StocksTrading.RegisterIndicatorForEquity(self, equity_symbol, indicator.Name, indicator)

def RegisterIndicatorForEquity(self, equity_symbol, indicator_name, indicator):
    StocksTrading.RegisterIndicatorForEquity(self, equity_symbol, indicator_name, indicator)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.