| Overall Statistics |
|
Total Orders 127 Average Win 0.39% Average Loss -0.42% Compounding Annual Return 3.366% Drawdown 13.700% Expectancy 0.232 Start Equity 100000 End Equity 102606.10 Net Profit 2.606% Sharpe Ratio -0.237 Sortino Ratio -0.252 Probabilistic Sharpe Ratio 21.922% Loss Rate 36% Win Rate 64% Profit-Loss Ratio 0.91 Alpha -0.064 Beta 0.531 Annual Standard Deviation 0.109 Annual Variance 0.012 Information Ratio -0.978 Tracking Error 0.1 Treynor Ratio -0.049 Total Fees $144.73 Estimated Strategy Capacity $0 Lowest Capacity Asset IWM RV0PWMLXVHPH Portfolio Turnover 6.67% Drawdown Recovery 200 Avg. Lost% Per Losser -3.62% Avg. Win% Per Winner 2.48% Max Win% 11.76% Max Loss% -13.86% *Profit Ratio 1.68 |
'''
Usage:
def Initialize(self):
self.log = Log(self)
# code xxxxxx
self.log.log("---->1")
'''
from AlgorithmImports import *
import time
class Log(AlphaModel):
def __init__(self, algo):
self.timer = round(time.time() * 1000)
self.algo = algo
self.maxLine = 500
self.count = 0
self.debug(f"Live mode={self.algo.live_mode}.....Log Initialized")
def log(self, message):
self.algo.Log(f"[LOG] {message}")
def info(self, message):
now = round(time.time() * 1000)
timer = (now - self.timer) / 1000
self.timer = now
if (self.algo.Time <= self.algo.Time.replace(hour=9, minute=35)):
self.algo.Log(f"[INFO] {message}")
def debug(self, message):
if (self.count < self.maxLine or self.algo.live_mode):
self.algo.Log(f"[DEUBG] {message}")
self.count += 1
def live(self, message):
if self.algo.live_mode and self.algo.warm_up_finished:
self.algo.Log(f"[DEUBG] {message}")
# region imports
from AlgorithmImports import *
from utils import Utils
from log import Log
# endregion
# lean cloud backtest "LLM02" --push --open
class LLM02(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 12, 31)
#self.set_end_date(2020, 3, 31)
self.set_cash(100000)
self.spy = self.add_equity("SPY", Resolution.DAILY).Symbol
self.set_benchmark(self.spy)
self.log = Log(self)
self.utils = Utils(self, self.spy)
self.utils.read_insight()
self.set_brokerage_model(BrokerageName.INTERACTIVE_BROKERS_BROKERAGE, AccountType.CASH)
self.settings.free_portfolio_value_percentage = 0.00
self.settings.rebalance_portfolio_on_insight_changes = True
self.settings.minimum_order_margin_portfolio_percentage = 0.01
self.set_execution(ImmediateExecutionModel())
self._smh = self.add_equity("SMH", Resolution.DAILY)
self._smh.set_settlement_model(ImmediateSettlementModel())
self._xlf = self.add_equity("XLF", Resolution.DAILY)
self._xlf.set_settlement_model(ImmediateSettlementModel())
self._ita = self.add_equity("ITA", Resolution.DAILY)
self._ita.set_settlement_model(ImmediateSettlementModel())
self._ibit = self.add_equity("IBIT", Resolution.DAILY)
self._ibit.set_settlement_model(ImmediateSettlementModel())
self._qqq = self.add_equity("QQQ", Resolution.DAILY)
self._qqq.set_settlement_model(ImmediateSettlementModel())
self._xli = self.add_equity("XLI", Resolution.DAILY)
self._xli.set_settlement_model(ImmediateSettlementModel())
self._gld = self.add_equity("GLD", Resolution.DAILY)
self._gld.set_settlement_model(ImmediateSettlementModel())
self._xle = self.add_equity("XLE", Resolution.DAILY)
self._xle.set_settlement_model(ImmediateSettlementModel())
self._xly = self.add_equity("XLY", Resolution.DAILY)
self._xly.set_settlement_model(ImmediateSettlementModel())
self._iwm = self.add_equity("IWM", Resolution.DAILY)
self._iwm.set_settlement_model(ImmediateSettlementModel())
self._schd = self.add_equity("SCHD", Resolution.DAILY)
self._schd.set_settlement_model(ImmediateSettlementModel())
self._xlv = self.add_equity("XLV", Resolution.DAILY)
self._xlv.set_settlement_model(ImmediateSettlementModel())
self._xlp = self.add_equity("XLP", Resolution.DAILY)
self._xlp.set_settlement_model(ImmediateSettlementModel())
self._cibr = self.add_equity("CIBR", Resolution.DAILY)
self._cibr.set_settlement_model(ImmediateSettlementModel())
self._vgk = self.add_equity("VGK", Resolution.DAILY)
self._vgk.set_settlement_model(ImmediateSettlementModel())
self._xlu = self.add_equity("XLU", Resolution.DAILY)
self._xlu.set_settlement_model(ImmediateSettlementModel())
self._igv = self.add_equity("IGV", Resolution.DAILY)
self._igv.set_settlement_model(ImmediateSettlementModel())
self._wcld = self.add_equity("WCLD", Resolution.DAILY)
self._wcld.set_settlement_model(ImmediateSettlementModel())
self._mchi = self.add_equity("MCHI", Resolution.DAILY)
self._mchi.set_settlement_model(ImmediateSettlementModel())
self._fxi = self.add_equity("FXI", Resolution.DAILY)
self._fxi.set_settlement_model(ImmediateSettlementModel())
self._inda = self.add_equity("INDA", Resolution.DAILY)
self._inda.set_settlement_model(ImmediateSettlementModel())
self._ewj = self.add_equity("EWJ", Resolution.DAILY)
self._ewj.set_settlement_model(ImmediateSettlementModel())
self._shy = self.add_equity("SHY", Resolution.DAILY)
self._shy.set_settlement_model(ImmediateSettlementModel())
self._ezu = self.add_equity("EZU", Resolution.DAILY)
self._ezu.set_settlement_model(ImmediateSettlementModel())
self._hack = self.add_equity("HACK", Resolution.DAILY)
self._hack.set_settlement_model(ImmediateSettlementModel())
self._sgov = self.add_equity("SGOV", Resolution.DAILY)
self._sgov.set_settlement_model(ImmediateSettlementModel())
self._aumi = self.add_equity("AUMI", Resolution.DAILY)
self._aumi.set_settlement_model(ImmediateSettlementModel())
self._slvp = self.add_equity("SLVP", Resolution.DAILY)
self._slvp.set_settlement_model(ImmediateSettlementModel())
self._shld = self.add_equity("SHLD", Resolution.DAILY)
self._shld.set_settlement_model(ImmediateSettlementModel())
self._infr = self.add_equity("INFR", Resolution.DAILY)
self._infr.set_settlement_model(ImmediateSettlementModel())
self._fsta = self.add_equity("FSTA", Resolution.DAILY)
self._fsta.set_settlement_model(ImmediateSettlementModel())
self._xlc = self.add_equity("XLC", Resolution.DAILY)
self._xlc.set_settlement_model(ImmediateSettlementModel())
self._vea = self.add_equity("VEA", Resolution.DAILY)
self._vea.set_settlement_model(ImmediateSettlementModel())
self._eem = self.add_equity("EEM", Resolution.DAILY)
self._eem.set_settlement_model(ImmediateSettlementModel())
self._xbi = self.add_equity("XBI", Resolution.DAILY)
self._xbi.set_settlement_model(ImmediateSettlementModel())
self._xme = self.add_equity("XME", Resolution.DAILY)
self._xme.set_settlement_model(ImmediateSettlementModel())
self._icln = self.add_equity("ICLN", Resolution.DAILY)
self._icln.set_settlement_model(ImmediateSettlementModel())
self._xlb = self.add_equity("XLB", Resolution.DAILY)
self._xlb.set_settlement_model(ImmediateSettlementModel())
self._clou = self.add_equity("CLOU", Resolution.DAILY)
self._clou.set_settlement_model(ImmediateSettlementModel())
self._ura = self.add_equity("URA", Resolution.DAILY)
self._ura.set_settlement_model(ImmediateSettlementModel())
self._grid = self.add_equity("GRID", Resolution.DAILY)
self._grid.set_settlement_model(ImmediateSettlementModel())
self._vnq = self.add_equity("VNQ", Resolution.DAILY)
self._vnq.set_settlement_model(ImmediateSettlementModel())
self._ivv = self.add_equity("IVV", Resolution.DAILY)
self._ivv.set_settlement_model(ImmediateSettlementModel())
self._eufn = self.add_equity("EUFN", Resolution.DAILY)
self._eufn.set_settlement_model(ImmediateSettlementModel())
self._kweb = self.add_equity("KWEB", Resolution.DAILY)
self._kweb.set_settlement_model(ImmediateSettlementModel())
self._vcsh = self.add_equity("VCSH", Resolution.DAILY)
self._vcsh.set_settlement_model(ImmediateSettlementModel())
self._xlk = self.add_equity("XLK", Resolution.DAILY)
self._bkln = self.add_equity("BKLN", Resolution.DAILY)
self._lqd = self.add_equity("LQD", Resolution.DAILY)
self._ijh = self.add_equity("IJH", Resolution.DAILY)
self._qual = self.add_equity("QUAL", Resolution.DAILY)
self._iefa = self.add_equity("IEFA", Resolution.DAILY)
self._soxx = self.add_equity("SOXX", Resolution.DAILY)
self._agg = self.add_equity("AGG", Resolution.DAILY)
self._xlu = self.add_equity("XLU", Resolution.DAILY)
self._xlc = self.add_equity("XLC", Resolution.DAILY)
self._vug = self.add_equity("VUG", Resolution.DAILY)
self._lqd = self.add_equity("LQD", Resolution.DAILY)
self._soxx = self.add_equity("SOXX", Resolution.DAILY)
self._ita = self.add_equity("ITA", Resolution.DAILY)
self._xlu = self.add_equity("XLU", Resolution.DAILY)
self._xlp = self.add_equity("XLP", Resolution.DAILY)
self._iefa = self.add_equity("IEFA", Resolution.DAILY)
self._fez = self.add_equity("FEZ", Resolution.DAILY)
self._tip = self.add_equity("TIP", Resolution.DAILY)
self._xlk = self.add_equity("XLK", Resolution.DAILY)
self._qqq = self.add_equity("QQQ", Resolution.DAILY)
self._gld = self.add_equity("GLD", Resolution.DAILY)
self._agg = self.add_equity("AGG", Resolution.DAILY)
self._ief = self.add_equity("IEF", Resolution.DAILY)
self._smh = self.add_equity("SMH", Resolution.DAILY)
self._xlu = self.add_equity("XLU", Resolution.DAILY)
self._xli = self.add_equity("XLI", Resolution.DAILY)
self._xle = self.add_equity("XLE", Resolution.DAILY)
self._voo = self.add_equity("VOO", Resolution.DAILY)
self._agg = self.add_equity("AGG", Resolution.DAILY)
self._ibit = self.add_equity("IBIT", Resolution.DAILY)
self._xlv = self.add_equity("XLV", Resolution.DAILY)
self._xlb = self.add_equity("XLB", Resolution.DAILY)
self._oih = self.add_equity("OIH", Resolution.DAILY)
self._gld = self.add_equity("GLD", Resolution.DAILY)
self._xlf = self.add_equity("XLF", Resolution.DAILY)
self._iwm = self.add_equity("IWM", Resolution.DAILY)
self._iei = self.add_equity("IEI", Resolution.DAILY)
self._lqd = self.add_equity("LQD", Resolution.DAILY)
self._hyg = self.add_equity("HYG", Resolution.DAILY)
self._xlc = self.add_equity("XLC", Resolution.DAILY)
self._xle = self.add_equity("XLE", Resolution.DAILY)
self._silj = self.add_equity("SILJ", Resolution.DAILY)
self._xop = self.add_equity("XOP", Resolution.DAILY)
self._kbwb = self.add_equity("KBWB", Resolution.DAILY)
self._ppa = self.add_equity("PPA", Resolution.DAILY)
self._slvp = self.add_equity("SLVP", Resolution.DAILY)
self._xlk.set_settlement_model(ImmediateSettlementModel())
self._bkln.set_settlement_model(ImmediateSettlementModel())
self._lqd.set_settlement_model(ImmediateSettlementModel())
self._ijh.set_settlement_model(ImmediateSettlementModel())
self._qual.set_settlement_model(ImmediateSettlementModel())
self._iefa.set_settlement_model(ImmediateSettlementModel())
self._soxx.set_settlement_model(ImmediateSettlementModel())
self._agg.set_settlement_model(ImmediateSettlementModel())
self._xlu.set_settlement_model(ImmediateSettlementModel())
self._xlc.set_settlement_model(ImmediateSettlementModel())
self._vug.set_settlement_model(ImmediateSettlementModel())
self._lqd.set_settlement_model(ImmediateSettlementModel())
self._soxx.set_settlement_model(ImmediateSettlementModel())
self._ita.set_settlement_model(ImmediateSettlementModel())
self._xlu.set_settlement_model(ImmediateSettlementModel())
self._xlp.set_settlement_model(ImmediateSettlementModel())
self._iefa.set_settlement_model(ImmediateSettlementModel())
self._fez.set_settlement_model(ImmediateSettlementModel())
self._tip.set_settlement_model(ImmediateSettlementModel())
self._xlk.set_settlement_model(ImmediateSettlementModel())
self._qqq.set_settlement_model(ImmediateSettlementModel())
self._gld.set_settlement_model(ImmediateSettlementModel())
self._agg.set_settlement_model(ImmediateSettlementModel())
self._ief.set_settlement_model(ImmediateSettlementModel())
self._smh.set_settlement_model(ImmediateSettlementModel())
self._xlu.set_settlement_model(ImmediateSettlementModel())
self._xli.set_settlement_model(ImmediateSettlementModel())
self._xle.set_settlement_model(ImmediateSettlementModel())
self._voo.set_settlement_model(ImmediateSettlementModel())
self._agg.set_settlement_model(ImmediateSettlementModel())
self._ibit.set_settlement_model(ImmediateSettlementModel())
self._xlv.set_settlement_model(ImmediateSettlementModel())
self._xlb.set_settlement_model(ImmediateSettlementModel())
self._oih.set_settlement_model(ImmediateSettlementModel())
self._gld.set_settlement_model(ImmediateSettlementModel())
self._xlf.set_settlement_model(ImmediateSettlementModel())
self._iwm.set_settlement_model(ImmediateSettlementModel())
self._iei.set_settlement_model(ImmediateSettlementModel())
self._lqd.set_settlement_model(ImmediateSettlementModel())
self._hyg.set_settlement_model(ImmediateSettlementModel())
self._xlc.set_settlement_model(ImmediateSettlementModel())
self._xle.set_settlement_model(ImmediateSettlementModel())
self._silj.set_settlement_model(ImmediateSettlementModel())
self._xop.set_settlement_model(ImmediateSettlementModel())
self._kbwb.set_settlement_model(ImmediateSettlementModel())
self._ppa.set_settlement_model(ImmediateSettlementModel())
self._slvp.set_settlement_model(ImmediateSettlementModel())
self.schedule.on(
self.date_rules.month_start(self.spy),
self.time_rules.after_market_open(self.spy, 1),
self._monthly_rebalance
)
def _monthly_rebalance(self) -> None:
if self.time.year != 2025:
return
if self.time.month == 1:
self.set_holdings(self._xlk.symbol, 0.18)
self.set_holdings(self._smh.symbol, 0.14)
self.set_holdings(self._xli.symbol, 0.16)
self.set_holdings(self._xlf.symbol, 0.14)
self.set_holdings(self._bkln.symbol, 0.18)
self.set_holdings(self._lqd.symbol, 0.2)
elif self.time.month == 2:
self.liquidate()
self.set_holdings(self._xlc.symbol, 0.165)
self.set_holdings(self._xlf.symbol, 0.185)
self.set_holdings(self._xly.symbol, 0.16)
self.set_holdings(self._xli.symbol, 0.175)
self.set_holdings(self._ijh.symbol, 0.16)
self.set_holdings(self._xlb.symbol, 0.155)
elif self.time.month == 3:
self.liquidate()
self.set_holdings(self._xlu.symbol, 0.2)
self.set_holdings(self._xlv.symbol, 0.18)
self.set_holdings(self._qual.symbol, 0.1)
self.set_holdings(self._iefa.symbol, 0.08)
self.set_holdings(self._eem.symbol, 0.06)
self.set_holdings(self._xli.symbol, 0.14)
self.set_holdings(self._igv.symbol, 0.12)
self.set_holdings(self._soxx.symbol, 0.12)
elif self.time.month == 4:
self.liquidate()
self.set_holdings(self._xlu.symbol, 0.26)
self.set_holdings(self._xlp.symbol, 0.22)
self.set_holdings(self._agg.symbol, 0.3)
self.set_holdings(self._xle.symbol, 0.12)
self.set_holdings(self._xli.symbol, 0.1)
elif self.time.month == 5:
self.liquidate()
self.set_holdings(self._xlu.symbol, 0.2)
self.set_holdings(self._xlc.symbol, 0.2)
self.set_holdings(self._vug.symbol, 0.2)
self.set_holdings(self._lqd.symbol, 0.2)
self.set_holdings(self._soxx.symbol, 0.2)
elif self.time.month == 6:
self.liquidate()
self.set_holdings(self._ita.symbol, 0.12)
self.set_holdings(self._xlu.symbol, 0.16)
self.set_holdings(self._xlp.symbol, 0.14)
self.set_holdings(self._iefa.symbol, 0.18)
self.set_holdings(self._fez.symbol, 0.12)
self.set_holdings(self._tip.symbol, 0.28)
elif self.time.month == 7:
self.liquidate()
self.set_holdings(self._xlk.symbol, 0.18)
self.set_holdings(self._qqq.symbol, 0.12)
self.set_holdings(self._soxx.symbol, 0.1)
self.set_holdings(self._xlc.symbol, 0.15)
self.set_holdings(self._gld.symbol, 0.15)
self.set_holdings(self._agg.symbol, 0.18)
self.set_holdings(self._ief.symbol, 0.12)
elif self.time.month == 8:
self.liquidate()
self.set_holdings(self._smh.symbol, 0.1)
self.set_holdings(self._xlu.symbol, 0.15)
self.set_holdings(self._xli.symbol, 0.12)
self.set_holdings(self._xle.symbol, 0.1)
self.set_holdings(self._voo.symbol, 0.23)
self.set_holdings(self._agg.symbol, 0.25)
self.set_holdings(self._ibit.symbol, 0.05)
elif self.time.month == 9:
self.liquidate()
self.set_holdings(self._xlv.symbol, 0.09)
self.set_holdings(self._xlb.symbol, 0.08)
self.set_holdings(self._oih.symbol, 0.06)
self.set_holdings(self._gld.symbol, 0.1)
self.set_holdings(self._xlf.symbol, 0.09)
self.set_holdings(self._iwm.symbol, 0.08)
self.set_holdings(self._iei.symbol, 0.25)
self.set_holdings(self._lqd.symbol, 0.15)
self.set_holdings(self._hyg.symbol, 0.1)
elif self.time.month == 10:
self.liquidate()
self.set_holdings(self._ita.symbol, 0.18)
self.set_holdings(self._xlf.symbol, 0.17)
self.set_holdings(self._xlc.symbol, 0.15)
self.set_holdings(self._xle.symbol, 0.14)
self.set_holdings(self._silj.symbol, 0.1)
self.set_holdings(self._xop.symbol, 0.09)
self.set_holdings(self._kbwb.symbol, 0.07)
self.set_holdings(self._ppa.symbol, 0.05)
self.set_holdings(self._slvp.symbol, 0.05)
self.schedule.on(self.date_rules.every_day(), self.time_rules.before_market_close(self.spy, 1), self.before_market_close)
def before_market_close(self):
self.utils.plot()
def on_end_of_algorithm(self):
self.utils.stats()
self.utils.store_insight()
from AlgorithmImports import *
from Newtonsoft.Json import JsonConvert
import System
import psutil
class Utils():
def __init__(self, algo, ticker):
self.algo = algo
self.ticker = ticker
self.mkt = []
self.insights_key = f"{self.algo.project_id}/Live_{self.algo.live_mode}_insights"
self.algo.set_benchmark(ticker)
def plot(self):
if not self.algo.is_warming_up:
mkt_price = self.algo.History(self.ticker, 2, Resolution.DAILY)['close'].unstack(level= 0).iloc[-1]
self.mkt.append(mkt_price)
mkt_perf = 100000 * self.mkt[-1] / self.mkt[0]
self.algo.Plot('Strategy Equity', self.ticker, mkt_perf)
def pctc(no1, no2):
return((float(str(no2))-float(str(no1)))/float(str(no1)))
def stats(self):
df = None
trades = self.algo.trade_builder.closed_trades
for trade in trades:
data = {
'symbol': trade.symbol,
'time': trade.entry_time,
'entry_price': trade.entry_price,
'exit_price': trade.exit_price,
'pnl': trade.profit_loss,
'pnl_pct': (trade.exit_price - trade.entry_price)/trade.entry_price,
}
df = pd.concat([pd.DataFrame(data=data, index=[0]), df])
if df is not None:
profit = df.query('pnl >= 0')['pnl'].sum()
loss = df.query('pnl < 0')['pnl'].sum()
avgWinPercentPerWin = "{0:.2%}".format(df.query('pnl >= 0')['pnl_pct'].mean())
avgLostPercentPerLost = "{0:.2%}".format(df.query('pnl < 0')['pnl_pct'].mean())
maxLost = "{0:.2%}".format(df.query('pnl < 0')['pnl_pct'].min())
maxWin = "{0:.2%}".format(df.query('pnl > 0')['pnl_pct'].max())
self.algo.set_summary_statistic("*Profit Ratio", round(profit / abs(loss),2))
self.algo.set_summary_statistic("Avg. Win% Per Winner", avgWinPercentPerWin)
self.algo.set_summary_statistic("Avg. Lost% Per Losser", avgLostPercentPerLost)
self.algo.set_summary_statistic("Max Loss%", maxLost)
self.algo.set_summary_statistic("Max Win%", maxWin)
def read_insight(self):
if self.algo.object_store.contains_key(self.insights_key) and self.algo.live_mode:
insights = self.algo.object_store.read_json[System.Collections.Generic.List[Insight]](self.insights_key)
self.algo.log.debug(f"Read {len(insights)} insight(s) from the Object Store")
self.algo.insights.add_range(insights)
#self.algo.object_store.delete(self.insights_key)
def store_insight(self):
if self.algo.live_mode:
insights = self.algo.insights.get_insights(lambda x: x.is_active(self.algo.utc_time))
# If we want to save all insights (expired and active), we can use
# insights = self.insights.get_insights(lambda x: True)
self.algo.log.debug(f"Save {len(insights)} insight(s) to the Object Store.")
content = ','.join([JsonConvert.SerializeObject(x) for x in insights])
self.algo.object_store.save(self.insights_key, f'[{content}]')
def get_near_expiry_insights(self, sourceModel, symbol):
insights = self.algo.insights.get_insights(lambda insight: (insight.close_time_utc) == (self.algo.utc_time + timedelta(hours=1)) and insight.Symbol == symbol and insight.SourceModel == sourceModel and insight.is_active(self.algo.utc_time))
return len(insights) > 0
def trace_memory(self, name):
self.algo.log.debug(f"[{name}] RAM memory % used: {psutil.virtual_memory()[2]} / RAM Used (GB): {round(psutil.virtual_memory()[3]/1000000000,2)}")