| 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 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 -11.991 Tracking Error 0.012 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 |
import numpy as np # needed for NaN handling
import math # ceil and floor are useful for rounding
from datetime import timedelta
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")
import statistics
from System import *
from QuantConnect import *
import talib
class MyAlgorithm(QCAlgorithm):
def Initialize(self):
self.symbols = None
# over simplistic tracking of position age
self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
#self.SetSlippageModel(VolumeShareSlippageModel())
# SMA
self.SetStartDate(2019,1,1) #Set Start Date
self.SetEndDate(2020,6,28) #Set End Date
self.SetCash(1000)
#self.SetWarmUp(50, Resolution.Minute)
self.SetBenchmark("SPY")
self.UniverseSettings.Resolution = Resolution.Minute
self.UniverseSettings.Leverage = 1
self.AddSecurity("SPY", Resolution.Minute).Symbol
self.Max_Candidates = 100
self.Max_BuyOrdersAtOnce = 20
self.MyLeastPrice = 1.50
self.MyMostPrice = 5.00
self.MyFireSalePrice = self.MyLeastPrice
self.MyFireSaleAge = 6
#self.time = { };
self.averages = { };
#self.changes = None
#self.index = 0
self.SetSecurityInitializer(lambda x: x.SetMarketPrice(self.GetLastKnownPrice(x))) # esto es para resolution menor de day
#self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
self.SetUniverseSelection(FineFundamentalUniverseSelectionModel(self.CoarseSelectionFunction, self.FineSelectionFunction))
#BEFORE TRADING START en initialize
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen("SPY", -10), Action(self.before_trading_start))
# Rebalance
EveryThisManyMinutes = 10
TradingDayHours = 6.5
TradingDayMinutes = int(TradingDayHours * 60)
#self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.Every(timedelta(minutes=EveryThisManyMinutes)), Action(self.my_rebalance))
for minutz in range(1, TradingDayMinutes, EveryThisManyMinutes):
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.AfterMarketOpen("SPY", minutz), Action(self.my_rebalance))
# Prevent excessive Logging of canceled orders at market close.
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.BeforeMarketClose("SPY", 1), Action(self.cancel_open_orders))
def OnSecuritiesChanged(self, changes):
self.Debug("checking")
self.changes = changes
def CoarseSelectionFunction(self, coarse):
sorted(coarse, key = lambda x: x.DollarVolume, reverse = True)
# We are going to use a dictionary to refer the object that will keep the moving averages
#self.Debug('coarse ' +str(coarse))
for cf in coarse:
if cf.HasFundamentalData:
if cf.Symbol not in self.averages:
self.averages[cf.Symbol] = SymbolData(cf.Symbol)
# Updates the SymbolData object with current EOD price
avg = self.averages[cf.Symbol]
avg.update(cf.EndTime, cf.AdjustedPrice)
# Filter the values of the dict: we only want up-trending securities
#values = list(filter(lambda x: x.is_downtrend, self.averages.values()))
#values.sort(key = lambda x: x.scale , reverse = False)
values = sorted(self.averages.values(), key = lambda x: x.scale, reverse = True)[:self.Max_Candidates]
self.values = list(values)
#for x in self.values:
# self.Debug('values ' + str(x.symbol) + ' price ' + str(x.price) + ' scale ' + str(x.scale))
self.g = [x for x in self.values if (float(x.price) >= self.MyLeastPrice) and (float(x.price) <= self.MyMostPrice)]
return [ x.symbol for x in self.g[:self.Max_Candidates] ]
def FineSelectionFunction(self, fine):
self.filtered = [x for x in fine if (x.SecurityReference.SecurityType == 'ST00000001')
and (x.SecurityReference.IsDepositaryReceipt == False)
and not (x.CompanyReference.IsLimitedPartnership)
and (x.SecurityReference.IsPrimaryShare)
and (x.SecurityReference.ExchangeId != 'OTC')]
#and x.CompanyReference.StandardName == ".*L[. ]?P.?$"]
# Not when-issued equities.
LowVar = 0.06 * len(self.filtered)
HighVar = 0.4 * len(self.filtered)
self.filtered_h = [x.Symbol for x in self.filtered[:int(HighVar)]]
self.filtered_l = [x.Symbol for x in self.filtered[-int(LowVar):]]
self.symbols = self.filtered_h + self.filtered_l
return self.symbols
def before_trading_start(self):
#update prices of my active securities and do some checks about the time they have been in my portfolio
pass
def cancel_open_orders(self):
pass
def my_rebalance(self):
#do my buy and sells checking minute bars prices by comparing it to period daily prices mean
data = self.CurrentSlice
for symbol, symbol_data in self.averages.items():
if not (data.ContainsKey(symbol) and data[symbol] is not None):
continue
current_price = data[symbol].Price
mean = symbol_data.fast.Current.Value # daily mean
self.Quit(f"{symbol}; Current price: {current_price}; Mean: {mean}")
self.Quit()
def OnData(self, data):
pass
class SymbolData(object):
def __init__(self, symbol):
self.symbol = symbol
#SMA (daily resolution)
self.fast = SimpleMovingAverage(3)
self.slow = SimpleMovingAverage(45)
self.price = 0
self.is_downtrend = False
self.scale = 0
def update(self, time, value):
self.price = value
if self.fast.Update(time, value) and self.slow.Update(time, value):
fast = self.fast.Current.Value
slow = self.slow.Current.Value
self.is_downtrend = fast < slow
self.scale = (fast-slow)/slow
if self.is_downtrend:
self.scale = (fast - slow) / slow