Overall Statistics |
Total Orders 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Start Equity 100000.0 End Equity 100000 Net Profit 0% Sharpe Ratio 0 Sortino 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 -1.46 Tracking Error 0.648 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
# region imports from AlgorithmImports import * import requests import json import time # endregion from typing import List class CoinGeckoUniverse: def __init__(self, algorithm, categories): self.algorithm = algorithm self.categories = categories def fetch_symbols(self): all_symbols = [] for category in self.categories: url = f"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&category={category}" retry_attempts = 3 for attempt in range(retry_attempts): try: response = self.algorithm.download(url) if response: data = json.loads(response) symbols = [coin['symbol'].upper() + 'USD' for coin in data if 'symbol' in coin] all_symbols.extend(symbols) self.algorithm.debug(f"Fetching Symbols Successful") break else: print("Failed to fetch symbols for category:", category) break except Exception as e: print(f"Attempt {attempt + 1} failed: {e}") self.algorithm.debug(f"Attempt {attempt + 1} failed: {e}") self.algorithm.sleep(2000) # Wait before retrying (milliseconds) return all_symbols
# region imports from AlgorithmImports import * from datetime import timedelta # endregion class Criteria(object): def __init__(self, algorithm, crypto, ema_period, std_period): self.algorithm = algorithm self._symbol = crypto.symbol self._value = self._symbol.value self._volume_in_usd = crypto.volume_in_usd self._ema = ExponentialMovingAverage(ema_period) self._std = StandardDeviation(std_period) self.ema_value = 0 self.percentage_volatility = 0 self.ema_period = ema_period self.lookback_period = self.algorithm.look_back self.criteria_met = False def update(self, time, crypto_close, crypto_symbol): if self._ema.update(time, crypto_close) and self._std.update(time, crypto_close): self.ema_value = self._ema.current.value self.percentage_volatility = self._std.current.value / crypto_close * 100 self.criteria_met = crypto_close > self.ema_value def ema_criteria(self, symbol): # Fetch the historical EMA data ema_history = self.algorithm.indicator_history(self._ema, symbol, timedelta(days=self.lookback_period)) ema_values = ema_history.data_frame['current'] # Fetch the historical price data history = self.algorithm.history(symbol, self.lookback_period, Resolution.DAILY) # Ensure we have enough data if len(history) < self.lookback_period: self.algorithm.log(f"Not enough data for {symbol}. History length: {len(history)})") return False # Track the index of the last closing price below the EMA last_below_ema_index = None # Iterate through historical data to find the last close below EMA for index in range(len(history) - 1, -1, -1): close_price = history.iloc[index]['close'] ema_value = ema_values.iloc[index] if close_price < ema_value: last_below_ema_index = index break # If no closing price below EMA was found, return False if last_below_ema_index is None: return False # Check if any candle after the last_below_ema_index opened and closed above the EMA for index in range(last_below_ema_index + 1, len(history)): open_price = history.iloc[index]['open'] close_price = history.iloc[index]['close'] ema_value = ema_values.iloc[index] if open_price > ema_value and close_price > ema_value: return True return False
from AlgorithmImports import * from CoinGeckoUniverse import CoinGeckoUniverse from Criteria import Criteria class UniverseSelectionModel: def __init__(self, algorithm): self.algorithm = algorithm self.categories = ['layer-1', 'depin', 'proof-of-work-pow', 'proof-of-stake-pos', 'meme-token', 'dog-themed-coins', 'eth-2-0-staking', 'non-fungible-tokens-nft', 'governance', 'artificial-intelligence', 'infrastructure', 'layer-2', 'zero-knowledge-zk', 'storage', 'oracle', 'bitcoin-fork', 'restaking', 'rollup', 'metaverse', 'privacy-coins', 'layer-0-l0', 'solana-meme-coins', 'data-availabilit', 'internet-of-things-iot', 'frog-themed-coins', 'ai-agents', 'superchain-ecosystem', 'bitcoin-layer-2', 'bridge-governance-tokens', 'modular-blockchain', 'cat-themed-coins', 'cross-chain-communication', 'analytics', 'identity', 'wallets', 'masternodes'] self.coin_universe = CoinGeckoUniverse(self.algorithm, self.categories) self.tickers = self.coin_universe.fetch_symbols() self.count = 10 self.std_period = 20 self.ema_period = 20 self.criteria_by_symbol = {} def coarse_filters(self, coarse): for crypto in coarse: symbol = crypto.symbol if symbol.value in self.tickers: if symbol not in self.criteria_by_symbol: self.criteria_by_symbol[symbol] = Criteria(self.algorithm, crypto, self.ema_period, self.std_period) self.criteria_by_symbol[symbol].update(crypto.end_time, crypto.close, crypto.symbol) if self.algorithm.is_warming_up: return Universe.UNCHANGED ### filter logic using self.criteria_by_symbol filtered = [x for x in self.criteria_by_symbol.values() if x._volume_in_usd > 10000 and x.criteria_met] self.algorithm.Debug(f"First Symbol in Coarse Filtered: {filtered[0]._volume_in_usd if filtered else 'None'}") filtered.sort(key=lambda x: x.percentage_volatility, reverse=True) self.algorithm.Debug(f"Sorting Successful: {filtered[0]._value if filtered else 'None'}") for x in filtered[:self.count]: self.algorithm.debug('symbol: ' + str(x._value) + ' Volume: ' + str(x._volume_in_usd) + "$") self.algorithm.Debug(f"Length of criteria_by_symbol: {len(self.criteria_by_symbol)}") ### return symbols in self.criteria_by_symbol.keys() that pass the filter return [f._symbol for f in filtered]
from AlgorithmImports import * from CryptoUniverseSelection import UniverseSelectionModel class CryptoTradingAlgorithm(QCAlgorithm): def initialize(self): self.set_start_date(2020, 1, 1) self.set_brokerage_model(BrokerageName.KRAKEN, AccountType.CASH) self.btcusd = self.add_crypto("BTCUSD", Resolution.HOUR, Market.KRAKEN).symbol self.set_benchmark("BTCUSD") self.look_back = 35 self.set_warm_up(self.look_back, Resolution.DAILY) # Create an instance of the universe selection model self.universe_model = UniverseSelectionModel(self) # Define the universe # Add Kraken universe with a selection function self.add_universe(CryptoUniverse.kraken(self.universe_model.coarse_filters)) self.alpha_counter = 2 # self.schedule.on(self.date_rules.month_start("SPY"), # self.time_rules.midnight, # self.add_universe(CryptoUniverse.kraken(self.universe_model.coarse_filters))) def OnData(self, data): # for symbol in self.Securities.Keys: # self.SetHoldings(symbol, 0.01) pass