| Overall Statistics |
|
Total Trades 18 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 $18.00 Estimated Strategy Capacity $0 Lowest Capacity Asset AAPL.EODDATA 2S |
from asyncio import FastChildWatcher
from AlgorithmImports import *
import numpy as np
from dateutil.parser import parse
class FormalRedChicken(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 10, 11) # Set Start Date
self.SetEndDate(2013, 10, 11)
self.SetCash(10000) # Set Strategy Cash
self.symbol = self.AddData(EODDATA, "AAPL", Resolution.Minute).Symbol
self.sum_p = 0
self.sum_n = 0
self.tick_list_p = []
self.tick_seq_p = []
self.tick_list_n = []
self.tick_seq_n = []
self.ts_p = int(self.GetParameter("tick_size_p"))
self.ts_n = int(self.GetParameter("tick_size_n"))
self.window_size_p = int(self.GetParameter("window_size_p"))
self.window_size_n = int(self.GetParameter("window_size_n"))
self.next_positive_prob = float(self.GetParameter("positive_p"))
self.next_negative_prob = float(self.GetParameter("negative_p"))
#Reality Modeling
self.interests = self.AddData(DFFData, "INT", Resolution.Daily).Symbol
#Benchmark
self.SetBenchmark(self.AddEquity("SPY").Symbol)
#IB Fee model
self.Securities[self.symbol].SetFeeModel(CustomFeeModel())
#Set slippage model
self.Securities[self.symbol].SetSlippageModel(ConstantSlippageModel(0.0002))
#Set Leverage interest model
self.Securities[self.symbol].MarginModel = BuyingPowerModel(2.0, 0.05)
self.cash_rate = 0.005
self.leverage_rate = .0075
self.short_rate = 0.0025
self.leverage_costs = 0
self.cash_interests = 0
self.short_costs = 0
self.max_leverage = 2
self.qt_factor = 1.5
#Schedule events
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(0,0), self.Cash_Rebalance)
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(20,0), self.Leverage_Rebalance)
self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(20,0), self.Short_Rebalance)
self.debug = True
def OnData(self, data):
if not data.ContainsKey(self.symbol): return
if self.debug:
self.Debug(f"Last price: {data[self.symbol].Value}")
self.Debug(f"Last qty: {data[self.symbol].GetProperty('Volume')}")
self.tick_list_p.append(data[self.symbol].Value)
self.sum_p = self.sum_p + data[self.symbol].GetProperty('Volume')
self.tick_list_n.append(data[self.symbol].Value)
self.sum_n = self.sum_n + data[self.symbol].GetProperty('Volume')
if self.sum_p >= self.ts_p:
self.sum_p = 0
if self.tick_list_p[0] < self.tick_list_p[-1]:
self.tick_seq_p.append(1)
else:
self.tick_seq_p.append(-1)
self.tick_list_p.clear()
if self.debug:
self.Debug('New Tick! (pos)')
self.Debug('Tick seq ' + str(self.tick_seq_p))
self.Debug('Sum ' + str(sum(self.tick_seq_p[-(self.window_size_p):])))
total_leverage = float(self.Portfolio.TotalPortfolioValue) * self.max_leverage
qt = (total_leverage * (float(self.qt_factor)/self.max_leverage)) / data[self.symbol].Value
if self.next_positive_prob > 0.6:
if not self.Portfolio.Invested:
if sum(self.tick_seq_p[-(self.window_size_p):]) == self.window_size_p:
self.MarketOrder(self.symbol, qt)
if self.debug:
self.Debug('Bought ' +str(qt)+ ' stocks at ' + str(data[self.symbol].Value))
else:
if self.Portfolio[self.symbol].IsLong:
if self.tick_seq_p[-1]==-1:
self.Liquidate()
if self.debug:
self.Debug('Liqudated')
if self.sum_n >= self.ts_n:
self.sum_n = 0
if self.tick_list_n[0] < self.tick_list_n[-1]:
self.tick_seq_n.append(1)
else:
self.tick_seq_n.append(-1)
self.tick_list_n.clear()
if self.debug:
self.Debug('New Tick! (neg)')
self.Debug('Tick seq ' + str(self.tick_seq_n))
self.Debug('Sum ' + str(sum(self.tick_seq_n[-(self.window_size_n):])))
total_leverage = float(self.Portfolio.TotalPortfolioValue) * self.max_leverage
qt = (total_leverage * (float(self.qt_factor)/self.max_leverage)) / data[self.symbol].Value
if self.next_negative_prob > 0.6:
if not self.Portfolio.Invested:
if sum(self.tick_seq_n[-(self.window_size_n):]) == -self.window_size_n:
self.MarketOrder(self.symbol, -qt)
if self.debug:
self.Debug('Shorted ' +str(qt)+ ' stocks at ' + str(data[self.symbol].Value))
else:
if self.Portfolio[self.symbol].IsShort:
if self.tick_seq_n[-1]==1:
self.SetHoldings(self.symbol, 0)
if self.debug:
self.Debug('Stoped short')
def OnEndOfAlgorithm(self):
self.ExitPositions()
def ExitPositions(self):
self.Liquidate()
self.Debug('TRADING FEES: ' + str(self.Portfolio[self.symbol].TotalFees))
self.Debug('LEVERAGE COSTS: ' + str(self.leverage_costs))
self.Debug('CASH INTERESTS: ' + str(self.cash_interests))
self.Debug('SHORT COSTS: ' + str(self.short_costs))
def Cash_Rebalance(self):
if not self.Portfolio.Invested:
data = self.Securities[self.interests].GetLastData()
if data:
cash = self.Portfolio.Cash
interest_rate = (data.Value / 100 - self.cash_rate)/360
if interest_rate < 0: return
else:
self.Portfolio.CashBook["USD"].AddAmount(cash * interest_rate)
self.cash_interests += cash * interest_rate
if self.debug:
self.Debug('Interest '+str(interest_rate))
self.Debug("Cash int " + str(cash * interest_rate))
def Leverage_Rebalance(self):
if self.Portfolio.Invested:
data = self.Securities[self.interests].GetLastData()
if data:
cash = self.Portfolio.Cash
interest_rate = (data.Value / 100 + self.leverage_rate)/360
self.Portfolio.CashBook["USD"].AddAmount(cash * interest_rate)
self.leverage_costs += cash * interest_rate
if self.debug:
self.Debug('Interest '+str(interest_rate))
self.Debug("Leverage int " + str(cash * interest_rate))
def Short_Rebalance(self):
if self.Portfolio[self.symbol].IsShort:
Last_order = self.Transactions.LastOrderId
mkt_value = self.Transactions.GetOrderTicket(Last_order).AverageFillPrice * self.Transactions.GetOrderTicket(Last_order).QuantityFilled
interest = self.short_rate / 360
self.short_costs += mkt_value * interest
self.Portfolio.CashBook["USD"].AddAmount(mkt_value * interest)
if self.debug:
self.Debug('Portfolio is short')
self.Debug('Short Interest ' + str(mkt_value * interest))
class CustomFeeModel:
def GetOrderFee(self, parameters):
if parameters.Order.Quantity > 0:
fee = min(max(1, parameters.Order.AbsoluteQuantity * 0.005), parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.01)
elif parameters.Order.Tag == 'Liquidated':
fee = min(max(1, parameters.Order.AbsoluteQuantity * 0.005), parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.01)
elif parameters.Order.Quantity < 0:
fee = min(max(1, parameters.Order.AbsoluteQuantity * 0.005), parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.01)
else:
fee = 0
return OrderFee(CashAmount(fee, 'USD'))
class DFFData(PythonData):
def GetSource(self, config, date, isLiveMode):
source = "https://www.dropbox.com/s/n4beqe9zlcv0y4t/DFF.csv?dl=1"
return SubscriptionDataSource( source, SubscriptionTransportMedium.RemoteFile) #rest for live data
def Reader(self, config, line, date, isLiveMode):
if not (line.strip() and line[0].isdigit()): return None
data = line.split(',')
coin = DFFData()
coin.Symbol = config.Symbol
coin.Time = parse(data[0])
coin.Value = float(data[1])
return coin
class EODDATA(PythonData):
def GetSource(self, config, date, isLiveMode):
source = "https://www.dropbox.com/s/lasp3l4ppgx97f3/AAPL_1m_2004-01-01_2022-03-01.csv?dl=1"
return SubscriptionDataSource( source, SubscriptionTransportMedium.RemoteFile)
def Reader(self, config, line, date, isLiveMode):
if not (line.strip() and line[0].isdigit()): return None
data = line.split(',')
coin = EODDATA()
coin.Symbol = config.Symbol
coin.Time = parse(data[0])
coin.Value = float(data[4])
coin["Volume"] = float(data[5])
return coin