| Overall Statistics |
|
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 |
class TradingSetup(object):
def __init__(self, symbol, entry, stop, profit, shares, order):
self.Symbol = symbol
self.Entry = entry
self.Stop = stop
self.Profit = profit
self.Shares = shares
self.StopEntryOrder = order
self.StopLossOrder = None
self.TakeProfitOrder = None
self.Active = True
self.Filled = False
######## NOT CURRENTLY IN USE ##########
class RollingWindowNum(object):
def __init__(self, symbol, size):
self.Symbol = symbol
self.Data = RollingWindow[float](size) #Is there a way to use Decimal instead of float? There would be an error if replace it by Decimal.
self.Error = True #No data in the beginning = no trades
class SymbolData(object):
def __init__(self, symbol, barPeriod, windowSize):
self.Symbol = symbol
self.BarPeriod = barPeriod
# A rolling window of data, data needs to be pumped into Bars by using Bars.Update( tradeBar ) and can be accessed like:
# mySymbolData.Bars[0] - most first recent piece of data
# mySymbolData.Bars[5] - the sixth most recent piece of data (zero based indexing)
self.Bars = RollingWindow[IBaseDataBar](windowSize)
# Returns true if all the data in this instance is ready (indicators, rolling windows, ect...)
def IsReady(self):
return self.Bars.IsReady and self.SMA.IsReady
# Returns true if the most recent trade bar time matches the current time minus the bar's period, this
# indicates that update was just called on this instance
def WasJustUpdated(self, current):
return self.Bars.Count > 0 and self.Bars[0].Time == current - self.BarPeriod# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm import *
from QuantConnect.Data.Consolidators import *
from QuantConnect.Data.Market import *
from QuantConnect.Indicators import *
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
from classes import *
from decimal import Decimal # Important: import decimal.Decimal class
class DayTrading(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2016,1,4) #Set Start Date
self.SetEndDate(2016,1,7) #Set End Date
self.SetCash(100000) #Set Strategy Cash
self.R = 200
#self.UniverseSettings.Resolution = Resolution.Minute
self.UniverseSettings.ExtendedMarketHours = True
self.AddUniverse("gapfinder", Resolution.Hour, self.Filter)
#self.AddUniverse(self.Filter)
self.AddEquity("SPY")
self.gappers = []
self.universe = []
self.LookingForBreakout = False #When true, the bot starts to look for high wave candle
self.PrevDay = self.Time - timedelta(1)
#self.PrevDayClose[sym] = RollingWindowNum(symbol, 5)
#threeMinConsolidator = TradeBarConsolidator(timedelta(minutes=3))
# attach our event handler. The event handler is a function that will
# be called each time we produce a new consolidated piece of data.
#threeMinConsolidator.DataConsolidated += self.threeMinBarHandler
# this call adds our 3-minute consolidator to
# the manager to receive updates from the engine
#self.SubscriptionManager.AddConsolidator(sym, threeMinConsolidator)
self.Schedule.On(self.DateRules.EveryDay("SPY"), \
self.TimeRules.AfterMarketOpen("SPY", 120), \
Action(self.MarketCloseLiquidate))
def Filter(self, coarse):
#if self.Time.hour != 0 and self.Time.hour != 16: # I'm looking at 9:00
# return self.universe
self.Log("test")
self.Log("c:"+str(coarse))
try:
sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
except:
return self.universe
filtered = [ x.Symbol for x in sortedByDollarVolume
if x.Price > 5 and x.DollarVolume > 10000000 ]
gappers = []
self.Log(filtered)
for sym in filtered:
if self.PrevDay != None :
bar = self.History(sym, self.PrevDay, self.PrevDay, Resolution.Daily)
if not bar.empty :
GapPercentage = (sym.Price - bar.close) / bar.close
self.Log(GapPercentage)
self.universe = gappers
return gappers
def threeMinBarHandler(self, sender, bar):
#This is our event handler for our 3-minute trade bar defined above in Initialize().
#So each time the consolidator produces a new 3-minute bar, this function will be called automatically.
#The sender parameter will be the instance of the IDataConsolidator that invoked the event
if bar.Symbol.Value not in self.gappers: #Only trade gappers.
return
if self.LookingForBreakout == True :
#self.Log("bar:" + str(bar.Symbol.Value))
#self.Log(self.gappers)
if self.IsHighWave(bar) :
self.Log("Highwave found! " + str(bar.High) + str(bar.Low) + str(bar.Open) + str(bar.Close))
newTicket = self.StopLimitOrder(bar.Symbol, round(self.R / (bar.High - bar.Low) ) , bar.High , bar.High)
self.Trades.append( TradingSetup(bar.Symbol, bar.High, bar.Low, 2*bar.High - bar.Low, round(self.R / (bar.High - bar.Low) ), newTicket) )
return
def IsHighWave(self, bar):
HighLowDiff = bar.High - bar.Low
OpenCloseDiff = bar.Open - bar.Close
if HighLowDiff / bar.Open >= 0.005 and ( OpenCloseDiff == 0 or ( HighLowDiff / OpenCloseDiff >= 2 and (bar.High - bar.Open) / OpenCloseDiff >=0.5 and (bar.Close - bar.Low) / OpenCloseDiff >=0.5 )) :
return True
return False
##### ORDER EVENT:entry triggered/stop triggered/tp triggered ######
def OnOrderEvent(self, orderEvent):
#order = self.Transactions.GetOrderById(orderEvent.OrderId)
self.Log(orderEvent)
for trade in self.Trades :
if orderEvent.OrderId == trade.StopEntryOrder.OrderId :
if orderEvent.Status == OrderStatus.Canceled :
return
if orderEvent.Status == OrderStatus.PartiallyFilled :
return #To trade live, it needs a better behaviour
if orderEvent.Status == OrderStatus.Filled :
trade.StopLossOrder = self.StopMarketOrder(trade.Symbol, -trade.Shares, trade.Stop)
trade.TakeProfitOrder = self.LimitOrder(trade.Symbol, -trade.Shares, trade.Profit)
self.Log("SL@"+str(trade.Stop)+":" + str(trade.StopLossOrder))
self.Log("TP@"+str(trade.Profit)+":" + str(trade.TakeProfitOrder))
return
if trade.StopLossOrder != None and orderEvent.OrderId == trade.StopLossOrder.OrderId and orderEvent.Status == OrderStatus.Filled :
#if trade.TakeProfitOrder != None:
trade.TakeProfitOrder.Cancel() #One cancel the other
return
if trade.TakeProfitOrder != None and orderEvent.OrderId == trade.TakeProfitOrder.OrderId and orderEvent.Status == OrderStatus.Filled :
#if trade.StopLossOrder != None:
trade.StopLossOrder.Cancel() #One cancel the other
return
def MarketCloseLiquidate(self):
self.Liquidate()
self.PrevDay = self.Time
openOrders = self.Transactions.GetOpenOrders()
if len(openOrders) > 0:
for x in openOrders:
self.Transactions.CancelOrder(x.Id)
#self.Log(str(x.Id) + " canceled")
def OnData(self, data):
self.data = data