| Overall Statistics |
|
Total Trades 38 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic 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 $603.56 Estimated Strategy Capacity $29000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X |
import numpy as np
import datetime
class GeekyFluorescentPinkFalcon(QCAlgorithm):
def Initialize(self):
# set up
self.SetStartDate(2020, 1, 1)
self.SetEndDate(2020, 1, 2)
self.SetCash(1000000)
self.SetBenchmark("SPY")
# data
equity = self.AddEquity("SPY", Resolution.Minute)
self.symbol = equity.Symbol
self.Consolidate(self.symbol, timedelta(hours=4), self.FourHourBarHandler)
self.Consolidate(self.symbol, Calendar.Weekly, self.WeeklyBarHandler)
# parameters
self.high_low_ratio = 1/2
self.high_open_ratio = 0.1
# init
self.high_open_distance = False
self.cond_1 = False
self.cond_2 = False
self.cond_retracement = False
self.low_minute = 0
self.open_minute = 0
self.high_minute = 0
self.open_low_mean = None
self.open_high_mean = None # mean of Open - High difference on 4H bar, window 100
self.rolling_high = RollingWindow[float](100)
self.rolling_low = RollingWindow[float](100)
self.rolling_open = RollingWindow[float](100)
# warm up
history = self.History([self.symbol], 100 * 5, Resolution.Hour)
for index, row in history.loc[self.symbol].iterrows():
self.rolling_high.Add(row.high)
self.rolling_low.Add(row.low)
self.rolling_open.Add(row.open)
self.SetWarmup(100 * 4 * 60)
# 4H Bar
def FourHourBarHandler(self, consolidated):
# reset
self.low_minute = 0
self.open_minute == 0
self.high_minute == 0
self.cond_retracement = False
self.cond_2 = False
self.cond_1 = False
# add data to rolling windows
self.rolling_high.Add(consolidated.High)
self.rolling_low.Add(consolidated.Low)
self.rolling_open.Add(consolidated.Open)
# check
if not self.rolling_high.IsReady: return
if not self.rolling_low.IsReady: return
if not self.rolling_open.IsReady: return
# mean of high - open diff
high_open = np.array(list(self.rolling_high)) - np.array(list(self.rolling_open ))
self.open_high_mean = np.mean(high_open)
# mean of open - low diff
open_low = np.array(list(self.rolling_open)) - np.array(list(self.rolling_low))
self.open_low_mean = np.mean(open_low)
# PROSJEK na 4H
# self.high_open_distance = (consolidated.High - consolidated.Open) < (high_open_mean * self.high_low_ratio) MINUTNOJ
# condition 1
# self.high_open_distance = (consolidated.High - consolidated.Open) < (high_open_mean * self.high_low_ratio)
# self.cond_2 = (consolidated.Open - consolidated.Low) > open_low_mean
# self.Debug(f"time {self.Time}, high_open_distance {self.high_open_distance}, cond_2 {self.cond_2}")
def OnOrderEvent(self, orderEvent):
order = self.Transactions.GetOrderById(orderEvent.OrderId)
if order.Status == OrderStatus.Filled:
if order.Type == OrderType.Limit or order.Type == OrderType.StopMarket: # or order.Type == OrderType.MarketOnOpen:
self.Transactions.CancelOpenOrders(order.Symbol)
def WeeklyBarHandler(self, consolidated):
pass
# self.Debug(f"{consolidated.EndTime},>> WeeklyBarHandler >> {consolidated.Close}")
# Miutni barovi
def OnData(self, data):
# # time restriction
# if self.Time.date < datetime.date(2020, 1, 1):
# return
# check for data
if not data.Bars.ContainsKey(self.symbol): return
if not data.ContainsKey(self.symbol): return
if data[self.symbol] is None: return
# check
if self.open_low_mean is None:
return
# set open 4H
self.Debug(f"Open: {self.open_minute}")
if self.open_minute == 0:
self.open_minute = data[self.symbol].Open
self.Debug(f"Open2: {self.open_minute}")
self.Debug(f"Close: {data[self.symbol].Close}")
# set low 4H
if self.low_minute == 0:
self.low_minute = data[self.symbol].Low
elif data[self.symbol].Low < self.low_minute:
self.low_minute = data[self.symbol].Low
# set high 4H
if self.high_minute == 0:
self.high_minute = data[self.symbol].High
elif data[self.symbol].High > self.high_minute:
self.high_minute = data[self.symbol].High
# condition 1: High - Open < mean(High - Open) * 0.01
# self.cond_1 = self.high_minute - self.open_minute < (self.open_high_mean * self.high_open_ratio) # old way
self.cond_1 = self.high_minute < self.rolling_high[0]
# cond 2
if self.cond_2 == False:
self.cond_2 = (self.open_minute - self.low_minute) > self.open_low_mean
# # 4H
# self.rolling_high
# # 1M
# data[self.symbol].High
# data[self.symbol].Low
# # 1M with 4H reset
# self.low_minute
# self.high_minute
# retracement
if self.cond_retracement == False and self.cond_1 and self.cond_2:
self.cond_retracement = (data[self.symbol].High - self.low_minute) > (self.open_minute - self.low_minute) * 0.4
# if self.cond_retracement:
# self.Debug("Retracement")
# order
if not self.Portfolio[self.symbol].Invested and not self.Portfolio[self.symbol].IsLong:
# DEBUG
self.Debug(f"time {self.Time}, high_minute: {self.high_minute}, open_minute: {self.open_minute}")
quantity = self.CalculateOrderQuantity(self.symbol, 1)
self.MarketOrder(self.symbol, -quantity, tag = "Buy!")
self.LimitOrder(self.symbol, quantity, self.low_minute) # Profit take (PT, TP)
self.StopMarketOrder(self.symbol, quantity, self.high_minute) # Stop loss (SL)
# 3 uvjeta:
# 1) High - Open < mean(High - Open) * 0.01
# 2) (Open - Low)_t > (Open - Low) * 3/4
# 3) retrace: High - Low > 0.4 * (open - low), High_t > (Open - Low)_t