Overall Statistics
Total Orders
248
Average Win
0.25%
Average Loss
-0.01%
Compounding Annual Return
247.210%
Drawdown
1.800%
Expectancy
12.154
Start Equity
100000.00
End Equity
113078.58
Net Profit
13.079%
Sharpe Ratio
11.954
Sortino Ratio
51.799
Probabilistic Sharpe Ratio
100.000%
Loss Rate
58%
Win Rate
42%
Profit-Loss Ratio
30.37
Alpha
1.429
Beta
-0.089
Annual Standard Deviation
0.116
Annual Variance
0.013
Information Ratio
5.644
Tracking Error
0.153
Treynor Ratio
-15.555
Total Fees
$0.00
Estimated Strategy Capacity
$2000.00
Lowest Capacity Asset
SOLGBP 2XR
Portfolio Turnover
684.11%
# region imports
from AlgorithmImports import *
# endregion

class CalmTanCoyote(QCAlgorithm):

    def initialize(self):
        self.set_start_date( datetime(2024, 11, 1, 9, 30) )
        self.set_end_date(datetime(2024, 12, 6, 12, 30))
        self.set_cash(100_000)
        # tickers = ['BTCBUSD','SOLGBP']
        # symbols = [ Symbol.create(ticker, SecurityType.CRYPTO, Market.BINANCE) for ticker in tickers ]#self.add_crypto('BTCBUSD',Resolution.MINUTE,Market.BINANCE).symbol
        self.btcusd = self.add_crypto('BTCUSD',Resolution.SECOND,Market.COINBASE).symbol
        self.solgbp = self.add_crypto('SOLGBP',Resolution.SECOND,Market.COINBASE).symbol

        momp_period = int(self.get_parameter("momp_period"))
        invest_period = int(self.get_parameter("invest_period"))
        # momp_threshold = float(self.get_parameter("momp_threshold"))
        
        self.settings.automatic_indicator_warm_up = True

        self.btcusd_momp = self.momp(self.btcusd,period = momp_period,resolution=Resolution.SECOND)

        self.invest_until=datetime(1900,1,1)

        # self.plot_indicator(self.btcusd_momp)
        # self.universe_settings.resolution = Resolution.MINUTE
        # self.add_universe_selection(ManualUniverse(symbols))

        self.invest_period = timedelta(seconds=invest_period)


    def on_data(self, data: Slice):
        "This function boils down to keeping the self.invest_until updated"

        # plotting
        if self.time.minute==0 and self.time.second==0:
            self.plot("Chart", self.btcusd_momp)
            try:
                df = self.history(TradeBar,self.btcusd,timedelta(seconds=4))
                if 'close' in df.columns:
                    close_list = df['close'].astype(str).to_list()
                    self.log(f"{','.join(close_list)}")
                self.log(f"{self.btcusd_momp.current.value=}")
            except Exception as e:
                pass
        
        # check that we are ready
        if not self.btcusd_momp.is_ready:
            return None
        
        # Check if we need to update when we should be in until
        if self.btcusd_momp.current.value > 0.2:
            self.log(f"{self.btcusd_momp.current.value}")
            # self.history()
            self.invest_until = self.time + self.invest_period
            self.log("{self.time=} {self.invest_until=}")

        if self.time<self.invest_until and not self.portfolio.invested:
            self.set_holdings(self.solgbp, 1)
        if self.time<self.invest_until and self.portfolio.invested:
            pass
        if self.invest_until < self.time and not self.portfolio.invested:
            pass
        if self.invest_until < self.time and self.portfolio.invested:
            self.log(f"{self.invest_until=} {self.time=} {self.portfolio.invested=}")
            self.liquidate()
            self.log(f"Liquidated")

    def my_plotting(self):
        self.plot("Chart", self.btcusd_momp)
        try:
            df = self.history(TradeBar,self.btcusd,timedelta(seconds=3))
            if 'close' in df.columns:
                close_list = df['close'].astype(str).to_list()
                self.log(f"{','.join(close_list)}")
            self.log(f"{self.btcusd_momp.current.value=}")
        except Exception as e:
            pass