diff --git a/strategy_api/.deployment b/strategy_api/.deployment new file mode 100644 index 0000000..6278331 --- /dev/null +++ b/strategy_api/.deployment @@ -0,0 +1,2 @@ +[config] +SCM_DO_BUILD_DURING_DEPLOYMENT=true \ No newline at end of file diff --git a/strategy_api/components/__pycache__/alert.cpython-312.pyc b/strategy_api/components/__pycache__/alert.cpython-312.pyc new file mode 100644 index 0000000..72ff452 Binary files /dev/null and b/strategy_api/components/__pycache__/alert.cpython-312.pyc differ diff --git a/strategy_api/components/__pycache__/marketData.cpython-312.pyc b/strategy_api/components/__pycache__/marketData.cpython-312.pyc new file mode 100644 index 0000000..20c5cce Binary files /dev/null and b/strategy_api/components/__pycache__/marketData.cpython-312.pyc differ diff --git a/strategy_api/components/alert.py b/strategy_api/components/alert.py new file mode 100644 index 0000000..7c5fd73 --- /dev/null +++ b/strategy_api/components/alert.py @@ -0,0 +1,66 @@ +from trycourier import Courier +from configparser import ConfigParser + +class alert: + def __init__(self, logger): + self.config = ConfigParser() + self.config.read("./config/config.ini") + self.client = Courier(auth_token="dk_prod_ZC8EG09G6BMB94MEGBFNVRX9SFN6") + self.toEmails = self.config.get("EmailConfig", "to_emails").split(",") + self.priceLimit = int(self.config.get("StrategyConfig", "price_limit")); + self.action = str(self.config.get("StrategyConfig", "action")); + self.logger = logger + + def setEmail(self, email): + self.toEmails = [email] + + def emailMomentum(self, subject, signal, result): + body = "" + body += "Top "+str(signal)+":\n" + for key, value in result.items(): + body += "\t"+str(key)+" : "+str(value) + body += "\n" + self.send_email(subject, body) + + def emailAgg(self, subject, buySignals, sellSignals): + body = "" + body += "Buy Signals:\n" + for value in buySignals: + if(int(round(buySignals[value], 2)) < self.priceLimit): + if(self.action == "highlight"): + body += "\t"+str(value)+" : "+str(round(buySignals[value], 2)) + body += " [High Risk]\n" + else: + self.logger.info("high risk symbol: "+str(value)+" : "+str(round(buySignals[value], 2))) + else: + body += "\t"+str(value)+" : "+str(round(buySignals[value], 2))+"\n" + body += "\n" + body += "Sell Signals:\n" + for value in sellSignals: + if(int(round(sellSignals[value], 2) < self.priceLimit)): + if(self.action == "highlight"): + body += "\t"+str(value)+" : "+str(round(sellSignals[value], 2)) + body += " [High Risk]\n" + else: + self.logger.info("high risk symbol: "+str(value)+" : "+str(round(sellSignals[value], 2))) + else: + body += "\t"+str(value)+" : "+str(round(sellSignals[value], 2))+"\n" + body += "\n" + self.send_email(subject, body) + + def send_email(self, subject, body): + for email in self.toEmails: + self.logger.info(email) + response = self.client.send( + event="Q5WTGPFQ01M9CKJ5Z3R1JQP2ZKEP", + recipient="mason", + profile={ + "email": email + }, + data={ + "subject": subject, + "message": body + } + ) + + self.logger.info(response['messageId']) diff --git a/strategy_api/components/marketData.py b/strategy_api/components/marketData.py new file mode 100644 index 0000000..689df28 --- /dev/null +++ b/strategy_api/components/marketData.py @@ -0,0 +1,179 @@ +import requests +import pandas as pd +from datetime import datetime, timedelta, date + +class marketData: + def __init__(self, logger, symbol, sector): + self.logger = logger + self.symbol = symbol + self.sector = sector + self.API_ENDPOINT = "https://api.binance.com/api/v3/klines" + self.ALPHA_VANTAGE_API_KEY = "6RTB6SLZGMV0N00L" + + def fetch_crypto_data(self, symbol, interval, start_date: date, end_date: date): + start_time = int(datetime.combine(start_date, datetime.min.time()).timestamp() * 1000) + end_time = int(datetime.combine(end_date, datetime.min.time()).timestamp() * 1000) + params = {"symbol": symbol, "interval": interval, "startTime": start_time, "endTime": end_time, "limit": 1000} + all_data = [] + + while True: + response = requests.get(self.API_ENDPOINT, params=params) + response.raise_for_status() + data = response.json() + if not data: + break + all_data.extend(data) + params["startTime"] = int(data[-1][0]) + 1 + if params["startTime"] > end_time: + break + + return [float(entry[4]) for entry in all_data] + + def fetch_stock_data(self, symbol, start_date: date, end_date: date): + url = f"https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={symbol}&apikey={self.ALPHA_VANTAGE_API_KEY}&outputsize=full" + try: + response = requests.get(url) + response.raise_for_status() + data = response.json() + + if "Time Series (Daily)" not in data: + self.logger.error(f"Alpha Vantage API error: {data.get('Note', 'No data returned.')}") + raise ValueError(f"No stock data available for {symbol}") + + prices = [] + for date_str, info in data["Time Series (Daily)"].items(): + date_dt = datetime.strptime(date_str, "%Y-%m-%d").date() + if start_date <= date_dt <= end_date: + prices.append(float(info["4. close"])) + + if not prices: + self.logger.error(f"No stock data found for {symbol} between {start_date} and {end_date}") + raise ValueError(f"No stock data available for {symbol}") + + return list(reversed(prices)) + + except requests.exceptions.RequestException as e: + self.logger.error(f"Failed fetching stock data from Alpha Vantage for {symbol}: {str(e)}") + raise + + end_time = int(datetime.utcnow().timestamp() * 1000) + start_time = int((datetime.utcnow() - timedelta(days=days)).timestamp() * 1000) + params = {"symbol": symbol, "interval": interval, "startTime": start_time, "endTime": end_time, "limit": 1000} + all_data = [] + while True: + response = requests.get(self.API_ENDPOINT, params=params) + response.raise_for_status() + data = response.json() + if not data: + break + all_data.extend(data) + params["startTime"] = int(data[-1][0]) + 1 + if params["startTime"] > end_time: + break + return [float(entry[4]) for entry in all_data] + + def fetch_market_data(self, interval, start_date: date, end_date: date): + symbol_details = self.symbol.split("-") + if len(symbol_details) == 2 and (symbol_details[1] == "USDT" or symbol_details[1] == "USDC" or symbol_details[1] == "USD"): + return self.fetch_crypto_data(symbol_details[0] + "USDC", interval, start_date, end_date) + else: + return self.fetch_stock_data(symbol_details[0], start_date, end_date) + + def get_current_crypto_price(self, symbol): + url = "https://api.binance.com/api/v3/ticker/price" + params = {"symbol": symbol} + response = requests.get(url, params=params) + return float(response.json()["price"]) + + def get_current_stock_price(self, symbol): + url = "https://www.alphavantage.co/query" + params = { + "function": "GLOBAL_QUOTE", + "symbol": symbol, + "apikey": self.ALPHA_VANTAGE_API_KEY + } + response = requests.get(url, params=params) + response.raise_for_status() + data = response.json() + return float(data["Global Quote"]["05. price"]) + + def get_current_price(self): + if self.sector == "crypto": + if "USDC" not in self.symbol: + self.symbol = self.symbol.split("-")[0] + "USDC" + return self.get_current_crypto_price(self.symbol) + elif self.sector == "tsx": + self.symbol = self.symbol + ".TO" + return self.get_current_stock_price(self.symbol) + elif self.sector == "sp500": + return self.get_current_stock_price(self.symbol) + else: + raise ValueError("Invalid sector provided.") + + def fetch_crypto_data_days(self, symbol, interval, days): + end_time = int(datetime.utcnow().timestamp() * 1000) + start_time = int((datetime.utcnow() - timedelta(days=days)).timestamp() * 1000) + params = {"symbol": symbol, "interval": interval, "startTime": start_time, "endTime": end_time, "limit": 1000} + all_data = [] + while True: + response = requests.get(self.API_ENDPOINT, params=params) + response.raise_for_status() + data = response.json() + if not data: + break + all_data.extend(data) + params["startTime"] = int(data[-1][0]) + 1 + if params["startTime"] > end_time: + break + + return [float(entry[4]) for entry in all_data] + + def fetch_stock_data_days(self, symbol, days, interval="60min"): + url = "https://www.alphavantage.co/query" + params = { + "function": "TIME_SERIES_INTRADAY", + "symbol": symbol, + "interval": interval, + "apikey": self.ALPHA_VANTAGE_API_KEY, + "outputsize": "full" + } + response = requests.get(url, params=params) + response.raise_for_status() + data = response.json() + + time_series_key = f"Time Series ({interval})" + if time_series_key not in data: + raise ValueError(f"Failed to fetch data for {symbol}, check symbol or API limit") + + all_prices = [] + end_datetime = datetime.utcnow() + start_datetime = end_datetime - timedelta(days=days) + + for timestamp, values in data[time_series_key].items(): + ts_datetime = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S") + if start_datetime <= ts_datetime <= end_datetime: + all_prices.append(float(values["4. close"])) + + return list(reversed(all_prices)) + + def fetch_market_data_days(self, interval, days): + if self.sector == "crypto": + if "USDC" not in self.symbol: + self.symbol = self.symbol + "USDC" + return self.fetch_crypto_data_days(self.symbol, interval, days) + elif self.sector == "tsx": + self.symbol = self.symbol + ".TO" + return self.fetch_stock_data_days(self.symbol, days) + elif sector == "sp500": + return self.fetch_stock_data_days(self.symbol, days) + else: + raise ValueError("Invalid sector provided.") + + def get_trading_days_back(self, start_date, num_days): + current_date = datetime.strptime(start_date, '%Y-%m-%d') + while num_days > 0: + current_date -= timedelta(days=1) + if current_date.weekday() in [5, 6]: + continue + num_days -= 1 + return current_date.strftime('%Y-%m-%d') diff --git a/strategy_api/config/config.ini b/strategy_api/config/config.ini new file mode 100644 index 0000000..8fccfd2 --- /dev/null +++ b/strategy_api/config/config.ini @@ -0,0 +1,15 @@ +[EmailConfig] +to_emails=jimmyyan1337@gmail.com +; to_emails=jimmyyan1337@gmail.com,tyblele@gmail.com +email_interval=30 + +[StrategyConfig] +price_limit=5 +action=remove + +[LoggerConfig] +level=INFO + +[Trading] +short=True +long=True \ No newline at end of file diff --git a/strategy_api/logs/test.log b/strategy_api/logs/test.log new file mode 100644 index 0000000..e69de29 diff --git a/strategy_api/main.py b/strategy_api/main.py new file mode 100644 index 0000000..3e5cde0 --- /dev/null +++ b/strategy_api/main.py @@ -0,0 +1,191 @@ +from fastapi import FastAPI, HTTPException +import uvicorn +import logging +from datetime import datetime +import csv +from fastapi.concurrency import run_in_threadpool +from pydantic import BaseModel +from datetime import date +from strategy.standardDeviation import standardDeviation +from strategy.coVariance import coVariance +from trader.alertTrader import alertTrader +from fastapi.middleware.cors import CORSMiddleware +from components.alert import alert + +dateCurrent = datetime.now().strftime("%Y_%m_%d") +logging.basicConfig(filename="./logs/"+str(dateCurrent)+"_strategyAPI.log", level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +app = FastAPI() + +class sdRequest(BaseModel): + sector: str + symbol: str + openSd: float + closeSd: float + is_buy: bool + +class cvRequest(BaseModel): + symbol1: str + symbol2: str + start_date: date + end_date: date + +class arRequest(BaseModel): + sector: str + email: str + +class nsRequest(BaseModel): + email: str + address: str + price: float + tag: str + description: str + link: str + parameters: str + +origins = ["*"] + +app.add_middleware( + CORSMiddleware, + allow_origins=origins, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +def get_crypto_list(): + try: + with open("./results/tokens.csv", mode="r") as file: + reader = csv.reader(file) + next(reader, None) + return {row[1]: int(row[2].replace("x", "")) for row in reader if len(row) > 2} + except Exception as e: + logger.error(f"Error reading crypto list: {str(e)}") + raise HTTPException(status_code=500, detail="Failed to retrieve crypto list.") + + +def get_symbols_from_file(filepath: str, col_index: int): + try: + with open(filepath, mode="r") as file: + lines = file.readlines() + return {line.split()[col_index]: 1 for line in lines if len(line.split()) > col_index} + except Exception as e: + logger.error(f"Error reading symbols from {filepath}: {str(e)}") + raise HTTPException(status_code=500, detail=f"Failed to retrieve symbols from {filepath}.") + +@app.get("/symbols/{sector}") +async def get_symbols(sector: str): + try: + if (sector.lower() == "crypto"): + return await run_in_threadpool(get_crypto_list) + elif (sector.lower() == "tsx"): + return await run_in_threadpool(get_symbols_from_file, "./results/tsx.txt", 1) + elif (sector.lower() == "sp500"): + return await run_in_threadpool(get_symbols_from_file, "./results/sp500.txt", 1) + else: + return {"error": "Invalid sector. Choose from 'crypto', 'tsx', or 'sp500'."} + except HTTPException as e: + raise e + except Exception as e: + logger.error(f"Unhandled error: {str(e)}") + raise HTTPException(status_code=500, detail="Failed to retrieve symbols.") + +@app.post("/standardDeviation") +async def executeSD(request: sdRequest): + try: + strategy = standardDeviation(logger, request.sector, request.symbol) + open_order_signal = await run_in_threadpool(strategy.next, request.sector, request.symbol, request.openSd) + close_order_signal = await run_in_threadpool(strategy.closeSignal, request.sector, request.symbol, request.is_buy, request.closeSd) + result = {"Open Order Signal": open_order_signal, "Close Open Signal": close_order_signal} + return result + except Exception as e: + logger.error(f"Error executing strategy SD: {str(e)}") + raise HTTPException(status_code=500, detail="Failed to execute strategy SD.") + +@app.post("/coVariance") +async def executeCV(request: cvRequest): + try: + strategy = coVariance(logger) + covariance = await run_in_threadpool(strategy.calculate_covariance, request.symbol1, request.symbol2, request.start_date, request.end_date) + result = {"Symbol1": request.symbol1, "Symbol2": request.symbol2, "CoVariance": covariance} + return result + except Exception as e: + logger.error(f"Error executing strategy CV: {str(e)}") + raise HTTPException(status_code=500, detail="Failed to execute strategy CV.") + +@app.post("/averageRebalance") +async def executeAR(request: arRequest): + try: + symbols = [] + if (request.sector.lower() == "crypto"): + symbols = await run_in_threadpool(get_crypto_list) + symbols = list(symbols.keys()) + elif (request.sector.lower() == "tsx"): + symbols = await run_in_threadpool(get_symbols_from_file, "./results/tsx.txt", 1) + elif (request.sector.lower() == "sp500"): + symbols = await run_in_threadpool(get_symbols_from_file, "./results/sp500.txt", 1) + else: + return {"error": "Invalid sector. Choose from 'crypto', 'tsx', or 'sp500'."} + + alert = alertTrader(symbols) + await run_in_threadpool(alert.runAverageRebalanceAlert, request.sector, request.email) + + result = "Email with results will be sent to: "+str(request.email) + return result + except Exception as e: + logger.error(f"Error executing strategy AR: {str(e)}") + raise HTTPException(status_code=500, detail="Failed to execute strategy AR.") + +@app.post("/momentum") +async def executeM(request: arRequest): + try: + symbols = [] + if (request.sector.lower() == "crypto"): + symbols = await run_in_threadpool(get_crypto_list) + symbols = list(symbols.keys()) + elif (request.sector.lower() == "tsx"): + symbols = await run_in_threadpool(get_symbols_from_file, "./results/tsx.txt", 1) + elif (request.sector.lower() == "sp500"): + symbols = await run_in_threadpool(get_symbols_from_file, "./results/sp500.txt", 1) + else: + return {"error": "Invalid sector. Choose from 'crypto', 'tsx', or 'sp500'."} + + alert = alertTrader(symbols) + await run_in_threadpool(alert.runMomentumAlert, request.sector, request.email) + + result = "Email with results will be sent to: "+str(request.email) + return result + except Exception as e: + logger.error(f"Error executing strategy M: {str(e)}") + raise HTTPException(status_code=500, detail="Failed to execute strategy M.") + +@app.post("/newStrategy") +async def executeNS(request: nsRequest): + try: + a = alert(logger) + a.setEmail("trivex.xyz@gmail.com") + + subject = f"New Strategy Submission: {request.tag}" + body = f""" + Email: {request.email} + Address: {request.address} + Price: {request.price} + Tag: {request.tag} + Description: {request.description} + Link: {request.link} + Parameters: {request.parameters} + """ + + a.send_email(subject, body) + a.setEmail(request.email) + a.send_email(subject, body) + + result = f"Email with results sent to: {request.email}" + return result + except Exception as e: + logger.error(f"Error executing strategy M: {str(e)}") + raise HTTPException(status_code=500, detail="Failed to execute strategy M.") + +if __name__ == '__main__': + uvicorn.run('main:app', host='0.0.0.0', port=8080) diff --git a/strategy_api/requirements.txt b/strategy_api/requirements.txt new file mode 100644 index 0000000..5bd7e99 --- /dev/null +++ b/strategy_api/requirements.txt @@ -0,0 +1,9 @@ +fastapi +uvicorn +jinja2 +python-multipart +trycourier==5.0.0 +yfinance==0.2.31 +pandas +pyodbc +matplotlib \ No newline at end of file diff --git a/strategy_api/results/sp500.txt b/strategy_api/results/sp500.txt new file mode 100644 index 0000000..0aa08ab --- /dev/null +++ b/strategy_api/results/sp500.txt @@ -0,0 +1,502 @@ +1 AAPL 3,902.91B +2 NVDA 3,433.99B +3 MSFT 3,266.37B +4 GOOG 2,408.66B +5 AMZN 2,408.46B +6 GOOGL 2,400.58B +7 META 1,534.26B +8 TSLA 1,483.95B +9 AVGO 1,123.47B +10 BRK.B 988.76B +11 WMT 744.53B +12 LLY 716.45B +13 JPM 682.19B +14 V 628.39B +15 MA 491.69B +16 ORCL 479.43B +17 XOM 467.64B +18 UNH 465.76B +19 COST 425.62B +20 NFLX 398.44B +21 PG 397.86B +22 HD 393.51B +23 JNJ 351.15B +24 BAC 340.52B +25 CRM 329.62B +26 ABBV 318.09B +27 KO 270.70B +28 TMUS 258.80B +29 CVX 258.49B +30 MRK 251.57B +31 CSCO 238.37B +32 WFC 238.36B +33 NOW 228.10B +34 ACN 226.19B +35 BX 214.62B +36 AXP 213.77B +37 PEP 212.09B +38 MCD 210.68B +39 IBM 207.50B +40 AMD 204.94B +41 MS 204.70B +42 DIS 203.84B +43 LIN 202.73B +44 TMO 202.33B +45 ABT 199.05B +46 ADBE 197.18B +47 GS 191.86B +48 ISRG 191.28B +49 PM 191.10B +50 PLTR 187.66B +51 GE 185.60B +52 INTU 180.70B +53 CAT 177.46B +54 QCOM 177.05B +55 TXN 175.55B +56 BKNG 169.55B +57 VZ 167.54B +58 DHR 166.66B +59 T 164.67B +60 BLK 163.37B +61 SPGI 156.46B +62 RTX 155.50B +63 PFE 151.54B +64 NEE 149.93B +65 HON 148.84B +66 CMCSA 146.94B +67 ANET 144.43B +68 PGR 142.49B +69 AMGN 142.17B +70 SYK 141.35B +71 LOW 141.29B +72 UNP 139.29B +73 TJX 138.82B +74 AMAT 137.00B +75 SCHW 137.00B +76 KKR 135.53B +77 ETN 134.98B +78 C 134.28B +79 BSX 134.22B +80 BA 134.00B +81 UBER 129.94B +82 COP 125.62B +83 PANW 124.36B +84 ADP 120.79B +85 FI 119.16B +86 DE 117.55B +87 BMY 117.15B +88 GILD 117.09B +89 LMT 115.70B +90 NKE 114.30B +91 CB 111.47B +92 ADI 108.24B +93 UPS 107.75B +94 MMC 105.12B +95 VRTX 105.12B +96 MDT 104.56B +97 SBUX 101.94B +98 MU 99.47B +99 PLD 98.62B +100 GEV 95.73B +101 LRCX 95.00B +102 EQIX 91.66B +103 SO 91.12B +104 MO 90.62B +105 CRWD 90.10B +106 PYPL 88.47B +107 INTC 87.99B +108 MCO 87.06B +109 KLAC 87.01B +110 SHW 86.97B +111 ELV 86.49B +112 APH 86.39B +113 ICE 86.39B +114 AMT 86.31B +115 CME 86.30B +116 TT 85.49B +117 CMG 84.87B +118 CDNS 84.63B +119 ABNB 84.34B +120 DUK 84.18B +121 PH 84.00B +122 DELL 83.31B +123 WM 82.43B +124 MDLZ 80.23B +125 MAR 79.59B +126 MSI 78.96B +127 WELL 78.83B +128 AON 78.20B +129 CI 77.90B +130 SNPS 77.31B +131 HCA 77.16B +132 PNC 77.01B +133 REGN 76.87B +134 ITW 76.53B +135 USB 76.18B +136 CTAS 76.00B +137 CL 75.48B +138 FTNT 74.97B +139 ZTS 74.31B +140 MCK 73.51B +141 TDG 73.19B +142 GD 73.00B +143 EMR 72.29B +144 CEG 71.87B +145 MMM 70.99B +146 ORLY 70.53B +147 COF 69.48B +148 NOC 68.64B +149 ECL 68.17B +150 EOG 67.96B +151 WMB 66.56B +152 APD 65.83B +153 BDX 65.62B +154 FDX 65.47B +155 SPG 65.09B +156 ADSK 64.72B +157 RCL 64.61B +158 RSG 63.93B +159 AJG 63.28B +160 CSX 62.81B +161 CARR 62.31B +162 HLT 61.74B +163 DLR 60.99B +164 KMI 60.72B +165 TGT 60.67B +166 OKE 59.70B +167 GM 58.84B +168 TFC 58.40B +169 AFL 57.35B +170 CPRT 56.95B +171 MET 56.95B +172 BK 56.75B +173 ROP 56.63B +174 FCX 56.36B +175 CHTR 56.10B +176 SRE 55.71B +177 CVS 55.68B +178 PCAR 55.15B +179 TRV 55.14B +180 AZO 55.10B +181 NXPI 54.75B +182 NSC 53.83B +183 JCI 53.63B +184 SLB 53.28B +185 GWW 53.13B +186 PSA 52.82B +187 AMP 52.27B +188 ALL 51.77B +189 FICO 51.25B +190 MNST 51.07B +191 PAYX 50.91B +192 ROST 49.65B +193 AEP 49.19B +194 PWR 48.83B +195 VST 48.77B +196 CMI 48.54B +197 AXON 48.14B +198 URI 47.74B +199 MSCI 47.64B +200 LULU 46.97B +201 O 46.74B +202 PSX 46.08B +203 FANG 46.07B +204 HWM 45.52B +205 AIG 45.44B +206 NDAQ 45.36B +207 DHI 45.30B +208 D 45.17B +209 OXY 45.15B +210 KR 44.74B +211 EW 44.46B +212 DFS 44.36B +213 FIS 44.33B +214 KMB 44.08B +215 KDP 44.02B +216 COR 43.98B +217 TEL 43.53B +218 MPC 43.50B +219 NEM 43.42B +220 PCG 43.22B +221 FAST 43.03B +222 PEG 42.74B +223 AME 42.57B +224 PRU 42.46B +225 KVUE 41.34B +226 GLW 41.01B +227 STZ 40.92B +228 GRMN 40.52B +229 LHX 40.46B +230 BKR 40.36B +231 DAL 40.11B +232 HES 40.09B +233 F 39.82B +234 CBRE 39.68B +235 CCI 39.55B +236 CTVA 39.51B +237 CTSH 39.41B +238 TRGP 39.41B +239 VRSK 39.33B +240 XEL 39.17B +241 EA 39.13B +242 A 38.87B +243 ODFL 38.76B +244 SYY 38.08B +245 IT 37.79B +246 EXC 37.70B +247 YUM 37.67B +248 VLO 37.62B +249 LVS 37.62B +250 OTIS 37.55B +251 LEN 37.43B +252 IR 37.22B +253 KHC 37.05B +254 IQV 36.30B +255 GEHC 36.26B +256 GIS 35.20B +257 VMC 34.91B +258 ACGL 34.73B +259 HSY 34.50B +260 RMD 34.13B +261 WAB 34.01B +262 IDXX 33.87B +263 CCL 33.73B +264 UAL 33.27B +265 EXR 32.99B +266 ROK 32.99B +267 ETR 32.69B +268 MLM 32.59B +269 TTWO 32.56B +270 EFX 32.38B +271 DD 32.29B +272 RJF 32.09B +273 HIG 32.05B +274 WTW 31.83B +275 AVB 31.72B +276 MTB 31.68B +277 DECK 31.60B +278 MCHP 31.45B +279 HPQ 31.36B +280 DXCM 31.34B +281 EIX 31.07B +282 ED 31.03B +283 IRM 30.98B +284 VICI 30.82B +285 HUM 30.77B +286 LYV 30.74B +287 CNC 30.71B +288 EBAY 30.55B +289 MPWR 30.22B +290 WEC 30.07B +291 ANSS 29.98B +292 CSGP 29.91B +293 BRO 29.70B +294 TSCO 29.11B +295 STT 29.10B +296 GDDY 29.02B +297 ON 28.91B +298 FITB 28.86B +299 HPE 28.79B +300 CAH 28.76B +301 GPN 28.75B +302 XYL 28.70B +303 KEYS 28.38B +304 SW 28.25B +305 EQR 28.23B +306 DOW 28.16B +307 PPG 28.03B +308 K 27.86B +309 NUE 27.57B +310 EL 26.95B +311 TPL 26.68B +312 EQT 26.60B +313 BR 26.57B +314 MTD 26.30B +315 DOV 26.11B +316 CHD 26.08B +317 FTV 26.02B +318 TROW 26.01B +319 SYF 25.94B +320 WBD 25.88B +321 TYL 25.65B +322 VLTO 25.59B +323 NVR 25.31B +324 VTR 25.07B +325 DTE 25.01B +326 AWK 24.50B +327 EXPE 24.34B +328 AEE 24.26B +329 ADM 24.23B +330 NTAP 24.16B +331 CPAY 24.14B +332 WST 24.10B +333 LYB 24.07B +334 PPL 24.06B +335 HBAN 23.91B +336 HAL 23.58B +337 CDW 23.50B +338 HUBB 23.19B +339 FE 22.99B +340 FOXA 22.83B +341 PHM 22.71B +342 CINF 22.71B +343 ROL 22.57B +344 PTC 22.48B +345 WRB 22.37B +346 FOX 22.16B +347 WAT 22.16B +348 TDY 22.14B +349 ERIE 22.10B +350 DRI 21.93B +351 RF 21.83B +352 SBAC 21.78B +353 ATO 21.77B +354 IFF 21.76B +355 BIIB 21.72B +356 ZBH 21.36B +357 WDC 21.33B +358 TER 21.17B +359 CNP 21.11B +360 ES 20.99B +361 MKC 20.94B +362 LUV 20.60B +363 STE 20.60B +364 TSN 20.55B +365 NTRS 20.54B +366 WY 20.53B +367 DVN 20.52B +368 PKG 20.40B +369 ZBRA 20.40B +370 CBOE 20.35B +371 CLX 20.23B +372 ULTA 20.19B +373 SMCI 20.10B +374 INVH 20.05B +375 CMS 19.96B +376 FSLR 19.94B +377 LDOS 19.43B +378 CFG 19.39B +379 VRSN 19.36B +380 LH 19.19B +381 IP 19.15B +382 ESS 19.10B +383 BF.B 18.85B +384 NRG 18.84B +385 STX 18.72B +386 FDS 18.67B +387 BBY 18.57B +388 MAA 18.56B +389 COO 18.52B +390 L 18.47B +391 PODD 18.46B +392 CTRA 18.22B +393 SNA 18.13B +394 STLD 17.82B +395 PFG 17.79B +396 TRMB 17.55B +397 ARE 17.38B +398 HRL 17.35B +399 JBHT 17.30B +400 KEY 17.22B +401 NI 17.21B +402 GEN 17.16B +403 BLDR 17.13B +404 DGX 17.12B +405 PNR 16.91B +406 MOH 16.88B +407 J 16.86B +408 OMC 16.85B +409 BALL 16.76B +410 JBL 16.67B +411 NWS 16.63B +412 HOLX 16.49B +413 DG 16.42B +414 GPC 16.31B +415 UDR 16.27B +416 IEX 16.07B +417 NWSA 16.05B +418 MAS 15.99B +419 KIM 15.95B +420 ALGN 15.94B +421 DLTR 15.78B +422 EG 15.57B +423 EXPD 15.56B +424 MRNA 15.50B +425 LNT 15.30B +426 AVY 15.22B +427 TPR 15.21B +428 FFIV 15.02B +429 DPZ 14.88B +430 CF 14.86B +431 BAX 14.85B +432 VTRS 14.80B +433 AKAM 14.56B +434 DOC 14.55B +435 SWKS 14.45B +436 RL 14.38B +437 TXT 14.33B +438 EVRG 14.20B +439 APTV 14.09B +440 EPAM 13.75B +441 RVTY 13.67B +442 AMCR 13.67B +443 REG 13.57B +444 INCY 13.47B +445 BXP 13.43B +446 POOL 13.38B +447 CAG 13.19B +448 KMX 13.07B +449 JKHY 12.92B +450 HST 12.74B +451 DVA 12.71B +452 CPT 12.61B +453 SWK 12.51B +454 JNPR 12.42B +455 CPB 12.41B +456 CHRW 12.33B +457 NDSN 12.10B +458 TAP 12.07B +459 UHS 11.95B +460 SJM 11.87B +461 PAYC 11.72B +462 DAY 11.71B +463 NCLH 11.62B +464 TECH 11.60B +465 ALLE 11.57B +466 SOLV 11.50B +467 AIZ 11.05B +468 BG 11.04B +469 BEN 10.93B +470 EMN 10.61B +471 ALB 10.58B +472 IPG 10.56B +473 MGM 10.34B +474 AOS 9.99B +475 ENPH 9.90B +476 PNW 9.73B +477 WYNN 9.66B +478 FRT 9.65B +479 LKQ 9.54B +480 CRL 9.53B +481 GL 9.29B +482 AES 9.26B +483 GNRC 9.20B +484 LW 9.08B +485 HSIC 8.73B +486 MKTX 8.65B +487 MTCH 8.34B +488 TFX 8.23B +489 APA 8.09B +490 IVZ 7.98B +491 HAS 7.97B +492 WBA 7.95B +493 MOS 7.71B +494 MHK 7.59B +495 HII 7.53B +496 CE 7.48B +497 CZR 7.08B +498 BWA 7.04B +499 PARA 6.95B +500 QRVO 6.76B +501 FMC 6.21B +502 AMTM 4.82B \ No newline at end of file diff --git a/strategy_api/results/tokens.csv b/strategy_api/results/tokens.csv new file mode 100644 index 0000000..c77a0af --- /dev/null +++ b/strategy_api/results/tokens.csv @@ -0,0 +1,83 @@ + +crypto,AAVE-USD,10x +crypto,ACE-USD,3x +crypto,ADA-USD,10x +crypto,AI-USD,3x +crypto,ALGO-USD,5x +crypto,ALT-USD,5x +crypto,APE-USD,10x +crypto,APT-USD,10x +crypto,AR-USD,5x +crypto,ARB-USD,10x +crypto,ARK-USD,3x +crypto,ATOM-USD,10x +crypto,AVAX-USD,10x +crypto,BADGER-USD,5x +crypto,BANANA-USD,3x +crypto,BCH-USD,10x +crypto,BIGTIME-USD,5x +crypto,BLAST-USD,3x +crypto,BLUR-USD,5x +crypto,BNB-USD,20x +crypto,BNT-USD,3x +crypto,BOME-USD,3x +crypto,kBONK-USD,10x +crypto,BRETT-USD,5x +crypto,BSV-USD,3x +crypto,BTC-USD,50x +crypto,CAKE-USD,3x +crypto,CATI-USD,3x +crypto,CELO-USD,3x +crypto,CFX-USD,5x +crypto,CHILLGUY-USD,3x +crypto,COMP-USD,5x +crypto,CRV-USD,10x +crypto,CYBER-USD,3x +crypto,DOGE-USD,20x +crypto,kDOGS-USD,3x +crypto,DOT-USD,10x +crypto,DYDX-USD,5x +crypto,DYM-USD,3x +crypto,EIGEN-USD,5x +crypto,ENA-USD,10x +crypto,ENS-USD,5x +crypto,ETC-USD,5x +crypto,ETH-USD,50x +crypto,ETHFI-USD,5x +crypto,FARTCOIN-USD,3x +crypto,FET-USD,5x +crypto,FIL-USD,10x +crypto,kFLOKI-USD,5x +crypto,FTM-USD,10x +crypto,FTT-USD,3x +crypto,FXS-USD,5x +crypto,SOL-USD,20x +crypto,STG-USD,3x +crypto,STRK-USD,5x +crypto,STX-USD,5x +crypto,SUI-USD,20x +crypto,SUPER-USD,3x +crypto,SUSHI-USD,5x +crypto,TAO-USD,5x +crypto,TIA-USD,10x +crypto,TNSR-USD,3x +crypto,TON-USD,10x +crypto,TRB-USD,3x +crypto,TRX-USD,10x +crypto,TURBO-USD,5x +crypto,UMA-USD,3x +crypto,UNI-USD,10x +crypto,USTC-USD,3x +crypto,USUAL-USD,5x +crypto,VIRTUAL-USD,5x +crypto,W-USD,5x +crypto,WIF-USD,10x +crypto,WLD-USD,10x +crypto,XAI-USD,3x +crypto,XLM-USD,5x +crypto,XRP-USD,20x +crypto,YGG-USD,3x +crypto,ZEN-USD,5x +crypto,ZETA-USD,3x +crypto,ZK-USD,5x +crypto,ZRO-USD,5x diff --git a/strategy_api/results/tsx.txt b/strategy_api/results/tsx.txt new file mode 100644 index 0000000..c2dbba6 --- /dev/null +++ b/strategy_api/results/tsx.txt @@ -0,0 +1,724 @@ +1 RY 245.54B +2 SHOP 204.84B +3 TD 133.38B +4 ENB 130.88B +5 BN 124.89B +6 TRI 105.34B +7 BMO 101.49B +8 CP 98.59B +9 CSU 96.37B +10 BNS 94.71B +11 CNR 93.11B +12 CNQ 92.80B +13 CM 87.20B +14 MFC 77.17B +15 ATD 76.40B +16 TRP 69.07B +17 WCN 64.13B +18 SU 63.68B +19 NGT 62.48B +20 L 57.70B +21 AEM 56.70B +22 SLF 49.00B +23 IFC 47.12B +24 IMO 46.94B +25 NA 46.31B +26 FFH 44.13B +27 GWO 43.88B +28 DOL 39.61B +29 ABX 39.42B +30 CVE 38.56B +31 WPM 37.48B +32 GIB.A 35.65B +33 BAM 33.58B +34 WSP 33.14B +35 CCO 32.93B +36 FNV 32.85B +37 QSP.UN 32.20B +38 NTR 31.59B +39 PPL 30.80B +40 QSR 30.57B +41 TECK.B 30.36B +42 TECK.A 30.36B +43 BCE 30.04B +44 FTS 29.86B +45 WN 29.70B +46 POW 29.20B +47 T 29.18B +48 H 26.68B +49 GFL 25.33B +50 RBA 24.13B +51 RCI.A 24.02B +52 RCI.B 24.02B +53 TOU 23.75B +54 IVN 23.73B +55 BIP.UN 21.26B +56 MRU 20.27B +57 MG 17.52B +58 TFII 17.19B +59 DAY 16.84B +60 K 16.64B +61 CLS 16.28B +62 BEP.UN 16.21B +63 EMA 15.87B +64 FM 15.72B +65 BEPC 15.39B +66 ARX 14.98B +67 OVV 14.52B +68 DSG 14.26B +69 BNT 14.21B +70 CCL.A 13.24B +71 CCL.B 13.24B +72 ATRL 13.19B +73 STN 13.07B +74 IAG 12.43B +75 X 12.36B +76 FSV 11.98B +77 EFN 11.73B +78 CAE 11.38B +79 AGI 11.09B +80 IGM 11.05B +81 PAAS 10.84B +82 SAP 10.61B +83 OTEX 10.56B +84 EMP.A 10.40B +85 GIL 10.36B +86 WFG 10.11B +87 KEY 9.97B +88 ALA 9.96B +89 CIGI 9.93B +90 LUN 9.64B +91 BBD.A 9.53B +92 BBD.B 9.53B +93 TIH 9.45B +94 CU 9.44B +95 BLCO 9.05B +96 CTC 8.62B +97 CTC.A 8.62B +98 CPX 8.39B +99 ONEX 8.16B +100 AC 7.97B +101 BIPC 7.93B +102 LUG 7.47B +103 QBR.B 7.24B +104 QBR.A 7.24B +105 CAR.UN 7.18B +106 SOBO 7.12B +107 ATZ 7.05B +108 BBU.UN 7.02B +109 CS 6.86B +110 NVEI 6.77B +111 PSK 6.71B +112 DFY 6.69B +113 SCR 6.40B +114 EDV 6.37B +115 TA 6.09B +116 MEG 6.06B +117 WCP 5.84B +118 PKI 5.72B +119 CWB 5.69B +120 NXE 5.62B +121 REI.UN 5.52B +122 ACO.X 5.44B +123 ACO.Y 5.44B +124 PRMW 5.38B +125 DOO 5.29B +126 FTT 5.11B +127 KXS 5.02B +128 OR 4.93B +129 AQN 4.93B +130 NPI 4.73B +131 BTO 4.70B +132 MX 4.70B +133 HBM 4.68B +134 BYD 4.63B +135 POU 4.57B +136 ELF 4.52B +137 GRT.UN 4.47B +138 ELD 4.43B +139 TFPM 4.39B +140 CHP.UN 4.38B +141 CIX 4.38B +142 ATS 4.38B +143 VRN 4.36B +144 FIL 4.31B +145 IMG 4.25B +146 CSH.UN 4.16B +147 TPZ 4.14B +148 GEI 4.01B +149 BHC 3.98B +150 SJ 3.95B +151 EQB 3.79B +152 SES 3.78B +153 STLC 3.71B +154 FCR.UN 3.61B +155 PBH 3.54B +156 LNR 3.53B +157 MDA 3.49B +158 TOY 3.44B +159 LSPD 3.43B +160 BB 3.34B +161 EQX 3.34B +162 GLXY 3.32B +163 HUT 3.27B +164 PEY 3.24B +165 BEI.UN 3.15B +166 PRU 3.13B +167 FIH.U 3.05B +168 WPK 3.04B +169 BLX 3.00B +170 NGEX 2.86B +171 NGD 2.86B +172 EIF 2.82B +173 BTE 2.80B +174 OGC 2.80B +175 CCA 2.78B +176 GSY 2.77B +177 CGG 2.75B +178 ATH 2.70B +179 NVA 2.70B +180 CIA 2.69B +181 AIF 2.59B +182 OLA 2.55B +183 BBUC 2.51B +184 MFI 2.51B +185 RUS 2.49B +186 CRR.UN 2.47B +187 HR.UN 2.46B +188 DML 2.44B +189 AG 2.43B +190 FN 2.42B +191 TXG 2.42B +192 TVE 2.41B +193 AP.UN 2.41B +194 WGX 2.40B +195 GMIN 2.38B +196 DPM 2.37B +197 NWC 2.36B +198 SSL 2.32B +199 TVK 2.25B +200 CEU 2.21B +201 RCH 2.16B +202 KMP.UN 2.10B +203 SSRM 2.09B +204 MAG 2.07B +205 VET 2.04B +206 DCBO 2.02B +207 ERO 2.01B +208 KNT 2.00B +209 SIL 1.97B +210 FVI 1.96B +211 IPCO 1.93B +212 MEQ 1.91B +213 FRU 1.91B +214 LIF 1.91B +215 WDO 1.89B +216 OSK 1.87B +217 TLRY 1.83B +218 TSU 1.81B +219 CXB 1.78B +220 CFP 1.78B +221 LNF 1.77B +222 EFX 1.76B +223 WELL 1.76B +224 PET 1.73B +225 CG 1.71B +226 ARE 1.71B +227 AND 1.68B +228 FOM 1.68B +229 CURA 1.68B +230 INE 1.67B +231 CJT 1.65B +232 DNTL 1.65B +233 NFI 1.65B +234 NG 1.58B +235 HWX 1.56B +236 PMZ.UN 1.55B +237 TCL.A 1.55B +238 TCL.B 1.55B +239 SEA 1.55B +240 SII 1.55B +241 JWEL 1.53B +242 AAV 1.53B +243 SPB 1.52B +244 ENGH 1.51B +245 HPS.A 1.51B +246 EFR 1.51B +247 IIP.UN 1.50B +248 TIXT 1.48B +249 ASTL 1.47B +250 BDT 1.46B +251 SVI 1.45B +252 SIS 1.45B +253 AYA 1.45B +254 PRL 1.44B +255 WTE 1.43B +256 GATO 1.41B +257 SKE 1.41B +258 GOOS 1.41B +259 EDR 1.39B +260 BIR 1.36B +261 IE 1.35B +262 SOY 1.35B +263 PXT 1.31B +264 KEL 1.30B +265 SFTC 1.30B +266 SIA 1.29B +267 MTL 1.29B +268 ALS 1.27B +269 LB 1.27B +270 ORA 1.27B +271 MRC 1.25B +272 BDGI 1.25B +273 KRR 1.21B +274 LAS.A 1.21B +275 CAS 1.19B +276 ZZZ 1.19B +277 PD 1.18B +278 DND 1.17B +279 CR 1.16B +280 PPTA 1.16B +281 BITF 1.16B +282 CHE.UN 1.13B +283 NWH.UN 1.12B +284 MTY 1.10B +285 CRON 1.09B +286 HRX 1.07B +287 PSI 1.07B +288 DTOL 1.06B +289 CVG 1.02B +290 CJ 1.01B +291 LAC 991.44M +292 GCG 990.69M +293 GCG.A 990.69M +294 AFN 984.84M +295 FSZ 962.97M +296 CF 959.86M +297 ET 949.21M +298 SVM 948.57M +299 CPLF 943.38M +300 DRM 934.86M +301 TCW 931.43M +302 ADEN 920.20M +303 PLC 904.87M +304 GDI 895.40M +305 ECN 879.98M +306 RUP 873.52M +307 AW 872.49M +308 ARIS 871.59M +309 IFP 868.54M +310 AAUC 867.50M +311 EXE 866.39M +312 MI.UN 866.20M +313 TKO 864.85M +314 CMG 861.87M +315 SEC 855.20M +316 SFC 850.62M +317 CUP.U 847.89M +318 TPX.B 834.75M +319 AOI 824.27M +320 NOA 823.59M +321 SGR.UN 820.72M +322 MATR 795.25M +323 CGX 789.02M +324 DBM 773.35M +325 RSI 770.96M +326 AX.UN 752.82M +327 SLS 747.29M +328 BLDP 730.59M +329 VZLA 720.69M +330 VLE 706.19M +331 MKP 700.92M +332 GFR 700.68M +333 KEC 687.98M +334 MDI 682.57M +335 TCS 675.83M +336 MRE 670.33M +337 AR 659.92M +338 CVO 659.16M +339 LAAC 649.28M +340 VNP 646.45M +341 PBL 635.94M +342 CTS 629.40M +343 MRG.UN 624.54M +344 FEC 623.72M +345 FCU 618.31M +346 MUX 603.13M +347 CHR 602.25M +348 URE 600.77M +349 TF 587.71M +350 VHI 585.09M +351 ALC 582.96M +352 HOM.U 579.81M +353 HOM.UN 579.81M +354 OBE 577.35M +355 BDI 574.19M +356 CGY 570.87M +357 SDE 564.24M +358 KSI 563.41M +359 SGY 554.04M +360 CGO 546.82M +361 MAL 545.72M +362 NXR.UN 541.23M +363 APR.UN 539.01M +364 GUD 529.21M +365 ESI 526.30M +366 BLN 525.92M +367 AI 519.69M +368 WFC 514.96M +369 RAY.A 502.58M +370 RAY.B 502.58M +371 DXT 500.01M +372 PMET 498.39M +373 VBNK 496.13M +374 MARI 494.98M +375 TAL 492.49M +376 ISC 490.62M +377 REAL 487.74M +378 ETG 486.10M +379 DIV 481.22M +380 WJX 468.61M +381 GAU 467.88M +382 HLF 465.76M +383 GTWO 464.12M +384 CNL 463.29M +385 ISO 461.33M +386 FC 439.70M +387 GBT 437.27M +388 TOT 435.42M +389 TWC 431.77M +390 PZA 430.44M +391 WEED 426.71M +392 MHC.UN 421.80M +393 PHX 419.87M +394 MSA 418.35M +395 TBL 411.27M +396 SOIL 410.24M +397 URC 410.13M +398 ACQ 405.65M +399 KBL 404.01M +400 BK 402.42M +401 PLZ.UN 398.49M +402 MND 393.48M +403 NDM 392.56M +404 NUAG 385.08M +405 AIDX 381.14M +406 GRA 380.46M +407 SOLG 378.40M +408 CPH 377.19M +409 DLCG 376.61M +410 BPF.UN 374.29M +411 MRD 372.86M +412 VCM 371.98M +413 ARR 370.53M +414 DR 369.09M +415 GTE 368.88M +416 TNZ 361.75M +417 GGD 359.18M +418 ERE.UN 354.42M +419 CSW.A 349.75M +420 CSW.B 349.75M +421 WILD 349.23M +422 QRC 348.17M +423 MRT.UN 347.80M +424 HTL 345.34M +425 TSAT 338.54M +426 STC 337.88M +427 MXG 337.57M +428 ACB 336.73M +429 LIRC 333.33M +430 NEO 332.76M +431 CKI 329.25M +432 RPI.UN 325.58M +433 CFW 323.73M +434 FVL 322.00M +435 PNE 318.71M +436 ADN 317.99M +437 PRV.UN 311.45M +438 PRB 307.95M +439 STEP 306.04M +440 PRN 301.19M +441 D.UN 300.28M +442 BTB.UN 296.94M +443 IAU 295.50M +444 MHC.U 294.91M +445 DRX 294.26M +446 WRN 293.39M +447 ORE 293.36M +448 XTC 290.97M +449 OGI 288.35M +450 DSV 288.33M +451 III 288.13M +452 ECOR 282.84M +453 KEI 278.00M +454 PIF 277.29M +455 ITE 276.56M +456 MPC 268.33M +457 MPC.C 268.33M +458 TSND 265.98M +459 KITS 265.24M +460 OLY 262.29M +461 ARG 261.61M +462 TC 252.71M +463 TMQ 252.68M +464 AIM 251.83M +465 FRX 244.28M +466 ECO 241.48M +467 VLN 227.73M +468 FAR 227.38M +469 AII 224.99M +470 GOLD 221.93M +471 PRYM 221.87M +472 LUC 220.04M +473 ACX 218.33M +474 FORA 218.09M +475 GH 211.72M +476 THNC 210.96M +477 GLO 210.71M +478 SYZ 208.81M +479 SHLE 206.56M +480 PTM 205.38M +481 DNG 204.05M +482 GIVX 199.44M +483 FCD.UN 199.40M +484 AMC 197.43M +485 WNDR 197.22M +486 RBY 197.06M +487 GDC 194.77M +488 ERD 190.48M +489 ASM 189.63M +490 ASCU 187.02M +491 AOT 186.43M +492 PAY 185.91M +493 ADW.B 185.07M +494 ADW.A 185.07M +495 DRT 183.74M +496 QTRH 181.73M +497 FTG 179.78M +498 SMT 175.73M +499 PRQ 174.53M +500 JAG 174.48M +501 ALYA 170.02M +502 KEG.UN 168.03M +503 VOXR 167.46M +504 LGO 160.28M +505 EPRX 159.95M +506 USA 158.64M +507 STGO 156.75M +508 FDY 156.06M +509 SBI 155.05M +510 LAM 154.37M +511 QIPT 152.11M +512 CXI 151.55M +513 Y 149.22M +514 NEXT 147.93M +515 HAI 147.90M +516 CRDL 147.70M +517 ANRG 147.29M +518 DRR.U 146.76M +519 MDNA 146.16M +520 IPO 145.99M +521 BRE 145.58M +522 TNT.UN 145.11M +523 GEO 141.96M +524 EDT 140.01M +525 IMP 132.01M +526 DC.A 131.44M +527 FF 129.58M +528 CNE 128.26M +529 BNE 126.90M +530 BRAG 126.54M +531 ITH 125.81M +532 ELVA 125.41M +533 GXE 125.21M +534 JOY 124.15M +535 CDR 124.12M +536 WEF 123.53M +537 HLS 123.04M +538 CRRX 121.71M +539 TH 119.55M +540 STCK 118.73M +541 DII.B 118.30M +542 HMM.A 117.88M +543 TRX 117.68M +544 PSD 116.52M +545 PNC.B 115.90M +546 PNC.A 115.90M +547 MNO 115.81M +548 E 115.72M +549 DCM 115.60M +550 MGA 115.31M +551 RCG 113.86M +552 FSY 112.18M +553 G 111.04M +554 GDL 110.88M +555 TLG 109.50M +556 ONC 108.67M +557 PYR 108.59M +558 SRV.UN 107.63M +559 COG 106.02M +560 TTNM 105.17M +561 XAU 104.57M +562 NANO 102.44M +563 BOS 101.74M +564 XTRA 99.38M +565 ILLM 99.33M +566 VGZ 99.24M +567 GRID 99.15M +568 MSCL 99.02M +569 QEC 98.56M +570 STLR 97.91M +571 YGR 97.75M +572 LGD 97.20M +573 GFP 96.42M +574 GCL 94.87M +575 SXP 94.31M +576 PNP 94.06M +577 CRP 93.43M +578 TXP 92.22M +579 XTG 86.62M +580 ARA 86.53M +581 WRG 86.30M +582 ROOT 86.14M +583 SAU 85.97M +584 WPRT 85.81M +585 TLO 84.12M +586 FURY 83.33M +587 LN 81.95M +588 KPT 81.80M +589 MDP 80.12M +590 TSL 79.65M +591 PEA 78.40M +592 LEV 78.05M +593 IS 77.66M +594 DYA 76.83M +595 MCB 75.56M +596 ELO 74.36M +597 XAM 74.26M +598 EXRO 72.10M +599 BUI 72.00M +600 SVA 71.57M +601 TRZ 71.07M +602 SLR 69.97M +603 MR.UN 67.93M +604 S 65.55M +605 GMX 65.04M +606 AKT.A 63.91M +607 BYL 60.47M +608 WM 60.31M +609 GCU 58.35M +610 TWM 55.95M +611 ICE 54.55M +612 MBX 53.56M +613 CFX 50.23M +614 TVA.B 49.25M +615 CCM 48.86M +616 HBP 47.55M +617 MOGO 46.38M +618 HOT.UN 45.96M +619 EAGR 45.60M +620 XLY 45.00M +621 PPR 41.87M +622 NPS 41.40M +623 EVO 40.48M +624 TI 38.18M +625 GURU 37.93M +626 CEMX 37.61M +627 SWP 37.59M +628 ATCU 37.29M +629 GENM 35.55M +630 AVCN 35.27M +631 BRMI 35.17M +632 ORV 34.84M +633 DBO 34.69M +634 CWL 34.58M +635 NPK 34.24M +636 SBR 33.89M +637 COPR 33.62M +638 BCT 33.60M +639 ACD 33.55M +640 FOOD 33.49M +641 BKI 33.45M +642 TSK 33.42M +643 WCM.A 33.05M +644 SOT.UN 32.96M +645 VGCX 32.51M +646 IFA 31.81M +647 AEG 31.56M +648 ELR 31.39M +649 NVO 31.06M +650 OGD 30.27M +651 UNI 29.47M +652 INO.UN 29.37M +653 RTG 28.22M +654 GMTN 27.78M +655 PMT 26.75M +656 LABS 26.72M +657 LCFS 26.16M +658 FANS 24.62M +659 TGO 24.36M +660 GVC 24.26M +661 SFI 24.13M +662 EGLX 23.08M +663 FT 23.02M +664 BEK.B 22.66M +665 CWEB 22.09M +666 BSX 22.03M +667 APS 21.73M +668 SGNL 21.68M +669 MPVD 21.22M +670 LSPK 20.70M +671 AVL 20.65M +672 OPT 19.88M +673 GRC 19.81M +674 CJR.B 16.95M +675 CHW 16.94M +676 WRX 16.33M +677 YRB 16.16M +678 RVX 15.44M +679 GRN 14.68M +680 ESM 14.39M +681 CFF 14.27M +682 HWO 14.19M +683 SFD 13.68M +684 GEC 13.49M +685 ELEF 13.48M +686 FLOW 13.16M +687 SGLD 13.14M +688 EXN 13.00M +689 NUMI 12.89M +690 NCF 12.14M +691 CSCI 11.84M +692 BU 11.41M +693 MSV 10.98M +694 DIAM 10.81M +695 CTX 10.74M +696 ADCO 9.38M +697 ASND 9.33M +698 CRWN 9.22M +699 VQS 9.14M +700 BRY 8.72M +701 WLLW 8.65M +702 SXI 8.51M +703 SAM 8.02M +704 BR 7.84M +705 AMM 7.55M +706 IVQ 7.31M +707 VRTS 6.40M +708 AAB 6.37M +709 KLS 5.99M +710 SVB 5.79M +711 SCY 5.32M +712 AVNT 5.31M +713 TMD 5.13M +714 KRN 5.06M +715 BNG 4.85M +716 APLI 4.24M +717 BABY 4.04M +718 MKZ.UN 3.13M +719 CNT 2.96M +720 FLNT 2.75M +721 AUMN 2.13M +722 SMC 1.96M +723 AXIS 606.87K +724 IOM 237.39K diff --git a/strategy_api/startup.sh b/strategy_api/startup.sh new file mode 100644 index 0000000..1227df9 --- /dev/null +++ b/strategy_api/startup.sh @@ -0,0 +1 @@ +python -m uvicorn main:app --host 0.0.0.0 diff --git a/strategy_api/strategy/__pycache__/averageRebalance.cpython-312.pyc b/strategy_api/strategy/__pycache__/averageRebalance.cpython-312.pyc new file mode 100644 index 0000000..cf0850a Binary files /dev/null and b/strategy_api/strategy/__pycache__/averageRebalance.cpython-312.pyc differ diff --git a/strategy_api/strategy/__pycache__/coVariance.cpython-312.pyc b/strategy_api/strategy/__pycache__/coVariance.cpython-312.pyc new file mode 100644 index 0000000..a4bc7b8 Binary files /dev/null and b/strategy_api/strategy/__pycache__/coVariance.cpython-312.pyc differ diff --git a/strategy_api/strategy/__pycache__/momentum.cpython-312.pyc b/strategy_api/strategy/__pycache__/momentum.cpython-312.pyc new file mode 100644 index 0000000..da54923 Binary files /dev/null and b/strategy_api/strategy/__pycache__/momentum.cpython-312.pyc differ diff --git a/strategy_api/strategy/__pycache__/standardDeviation.cpython-312.pyc b/strategy_api/strategy/__pycache__/standardDeviation.cpython-312.pyc new file mode 100644 index 0000000..a50113d Binary files /dev/null and b/strategy_api/strategy/__pycache__/standardDeviation.cpython-312.pyc differ diff --git a/strategy_api/strategy/averageRebalance.py b/strategy_api/strategy/averageRebalance.py new file mode 100644 index 0000000..92cb507 --- /dev/null +++ b/strategy_api/strategy/averageRebalance.py @@ -0,0 +1,47 @@ +import numpy as np + +class averageRebalance(): + def __init__(self, symbol, logger, data): + self.symbol = symbol + self.logger = logger + self.data = data + + def highest(self, num): + highestPrice = self.data[-1] + for i in range(num): + if(self.data[-i-1] > highestPrice): + highestPrice = self.data[-i-1] + return highestPrice + + def lowest(self, num): + lowestPrice = self.data[-1] + for i in range(num): + if(self.data[-i-1] < lowestPrice): + lowestPrice = self.data[-i-1] + return lowestPrice + + def sma(self, amount): + total = 0 + for i in range(amount): + total += self.data[-i] + average = total/amount + return average + + def roc(self, curPrice, prevPrice): + value = ((curPrice-prevPrice)/prevPrice)*100 + return value + + def next(self, curPrice): + weekly = 7 + monthly = 20 + deltaMax = 5 + if(curPrice < self.sma(monthly) and curPrice <= self.lowest(weekly)): + roc = self.roc(curPrice, self.highest(weekly)) + if(roc < -deltaMax): + return "Buy" + elif(curPrice >= self.highest(weekly) and curPrice > self.sma(monthly)): + roc = self.roc(curPrice, self.lowest(weekly)) + if(roc > deltaMax): + return "Sell" + else: + return "None" diff --git a/strategy_api/strategy/coVariance.py b/strategy_api/strategy/coVariance.py new file mode 100644 index 0000000..f44f2a5 --- /dev/null +++ b/strategy_api/strategy/coVariance.py @@ -0,0 +1,27 @@ +from datetime import datetime, timedelta, date +import requests +import numpy as np +from components.marketData import marketData + +class coVariance: + def __init__(self, logger): + self.logger = logger + + def calculate_covariance(self, symbol1, symbol2, start_date: date, end_date: date, interval="1d"): + md1 = marketData(self.logger, symbol1, "none") + md2 = marketData(self.logger, symbol2, "none") + + data1 = md1.fetch_market_data(interval, start_date, end_date) + data2 = md2.fetch_market_data(interval, start_date, end_date) + + min_length = min(len(data1), len(data2)) + data1 = data1[:min_length] + data2 = data2[:min_length] + + if len(data1) < 2 or len(data2) < 2: + self.logger.error("Not enough data points for covariance calculation.") + raise ValueError("Not enough data points to calculate covariance.") + + covariance = np.cov(data1, data2)[0, 1] + self.logger.info(f"Covariance between {symbol1} and {symbol2} from {start_date} to {end_date}: {covariance}") + return covariance diff --git a/strategy_api/strategy/momentum.py b/strategy_api/strategy/momentum.py new file mode 100644 index 0000000..919d3c2 --- /dev/null +++ b/strategy_api/strategy/momentum.py @@ -0,0 +1,69 @@ +import numpy as np + +class momentum(): + def __init__(self, symbolList, logger, data): + self.symbolList = symbolList + self.logger = logger + self.data = data + self.signal = "" + self.amount = 25 + + def roc(self, curPrice, prevPrice): + value = ((curPrice-prevPrice)/prevPrice)*100 + return value + + def sma(self, symbol, amount): + total = 0 + for i in range(amount): + total += self.data[symbol][-i] + average = total/amount + return average + + def getBottomSymbols(self): + bottomSymbols = [] + count = 0 + for key, value in self.rev_sorted_dict.items(): + bottomSymbols.append(key) + count += 1 + if count == self.amount: + break + return bottomSymbols + + def getTopSymbols(self): + topSymbols = [] + count = 0 + for key, value in self.sorted_dict.items(): + topSymbols.append(key) + count += 1 + if count == self.amount: + break + return topSymbols + + def getAllSymbols(self): + topSymbols = [] + for key, value in self.sorted_dict.items(): + topSymbols.append(key) + return topSymbols + + + def getSignal(self): + return self.signal + + def next(self, curPrice, day=7): + results = {} + temp = 0 + for symbol in self.symbolList: + if(self.roc(curPrice[symbol], self.data[symbol][-30]) < 3): + temp += 1 + results[symbol] = self.roc(curPrice[symbol], self.data[symbol][-day]) + + self.sorted_dict = dict(sorted(results.items(), key=lambda item: item[1], reverse=True)) + self.rev_sorted_dict = dict(sorted(results.items(), key=lambda item: item[1], reverse=False)) + + if(temp > 10): + self.signal = "short" + return self.getBottomSymbols() + else: + self.signal = "long" + # return self.getTopSymbols() + return self.getAllSymbols() \ No newline at end of file diff --git a/strategy_api/strategy/standardDeviation.py b/strategy_api/strategy/standardDeviation.py new file mode 100644 index 0000000..3d51e94 --- /dev/null +++ b/strategy_api/strategy/standardDeviation.py @@ -0,0 +1,69 @@ +import requests +from datetime import datetime, timedelta +import matplotlib.pyplot as plt +import numpy as np +from components.marketData import marketData + +class standardDeviation(): + def __init__(self, logger, sector, symbol): + self.logger = logger + self.signal = "" + self.md = marketData(self.logger, symbol, sector) + self.API_ENDPOINT = "https://api.binance.com/api/v3/klines" + self.ALPHA_VANTAGE_API_KEY = "6RTB6SLZGMV0N00L" + + def calculate_std_range(self, data, num_std_dev): + mean = np.mean(data) + std_dev = np.std(data) + upper_bound = mean + num_std_dev * std_dev + lower_bound = mean - num_std_dev * std_dev + return mean, upper_bound, lower_bound + + def plot_distribution(self, data): + plt.figure(figsize=(10, 6)) + plt.hist(data, bins=30, color="blue", alpha=0.7) + plt.title("Distribution of Closing Prices") + plt.xlabel("Closing Price") + plt.ylabel("Frequency") + plt.grid(axis="y", linestyle="--", alpha=0.7) + plt.show() + + def closeSignal(self, sector, symbol, is_buy, close_std_dev): + interval = "1h" + days = 14 + + closing_prices = self.md.fetch_market_data_days(interval, days) + mean, upper_bound, lower_bound = self.calculate_std_range(closing_prices, close_std_dev) + current_price = self.md.get_current_price() + + self.logger.info(f"Mean: {mean}") + self.logger.info(f"Upper Bound (+{close_std_dev} Std Dev): {upper_bound}") + self.logger.info(f"Lower Bound (-{close_std_dev} Std Dev): {lower_bound}") + self.logger.info(f"Current price: {current_price}") + + if is_buy and current_price > upper_bound: + return "close" + elif not is_buy and current_price < lower_bound: + return "close" + else: + return "none" + + def next(self, sector, symbol, open_std_dev): + interval = "1h" + days = 14 + + closing_prices = self.md.fetch_market_data_days(interval, days) + mean, upper_bound, lower_bound = self.calculate_std_range(closing_prices, open_std_dev) + current_price = self.md.get_current_price() + + self.logger.info(f"Mean: {mean}") + self.logger.info(f"Upper Bound (+{open_std_dev} Std Dev): {upper_bound}") + self.logger.info(f"Lower Bound (-{open_std_dev} Std Dev): {lower_bound}") + self.logger.info(f"Current price: {current_price}") + + if current_price < lower_bound: + return "long" + elif current_price > upper_bound: + return "short" + else: + return "none" diff --git a/strategy_api/trader/__pycache__/alertTrader.cpython-312.pyc b/strategy_api/trader/__pycache__/alertTrader.cpython-312.pyc new file mode 100644 index 0000000..9ba9ef0 Binary files /dev/null and b/strategy_api/trader/__pycache__/alertTrader.cpython-312.pyc differ diff --git a/strategy_api/trader/alertTrader.py b/strategy_api/trader/alertTrader.py new file mode 100644 index 0000000..7775a19 --- /dev/null +++ b/strategy_api/trader/alertTrader.py @@ -0,0 +1,105 @@ +from configparser import ConfigParser +from components.alert import alert +from components.marketData import marketData + +from strategy.averageRebalance import averageRebalance +from strategy.momentum import momentum +from configparser import ConfigParser + + +import logging +from datetime import datetime +import time +import pandas as pd + +class alertTrader: + def __init__(self, listSymbol): + date = datetime.now().strftime("%Y_%m_%d") + self.config = ConfigParser() + self.config.read("./config/config.ini") + self.level = self.config.get("LoggerConfig", "level"); + logging.basicConfig(filename="./logs/"+str(date)+".log", level=self.level.upper(), format='%(asctime)s - %(levelname)s - %(message)s') + self.logger = logging.getLogger(__name__) + + self.alert = alert(self.logger) + self.listSymbol = listSymbol + + def runAverageRebalanceAlert(self, sector, email): + self.alert.setEmail(email) + self.run(sector) + + def run(self, sector): + self.logger.info("**********Starting Alert Trader**********") + + buySignals = {} + sellSignals = {} + + listSymbol = self.listSymbol + alpha_api_key = "6RTB6SLZGMV0N00L" + + count = 1 + for symbol in listSymbol: + try: + md = marketData(self.logger, symbol, sector) + current_date = datetime.now().strftime('%Y-%m-%d') + num_trading_days_back = 25 + result_date = md.get_trading_days_back(current_date, num_trading_days_back) + data = md.fetch_market_data("1d", datetime.strptime(result_date, "%Y-%m-%d").date(), datetime.strptime(current_date, "%Y-%m-%d").date()) + curPrice = md.get_current_price() + averageRebalanceSym = averageRebalance(symbol, self.logger, data) + signal = averageRebalanceSym.next(curPrice) + + if signal == "Buy": + buySignals[symbol] = curPrice + elif signal == "Sell": + sellSignals[symbol] = curPrice + + print(f"{count}/{len(listSymbol)}") + self.logger.info(f"{count}/{len(listSymbol)}") + count += 1 + + except Exception as e: + self.logger.error(f"Error in: {symbol} with error... {str(e)}") + + self.alert.emailAgg("Trivex Average Rebalance Alert Signal !!!", buySignals, sellSignals) + self.logger.info("**********Finishing Alert Trader**********") + + def runMomentumAlert(self, sector, email): + self.alert.setEmail(email) + self.runMomentum(sector) + + def runMomentum(self, sector): + self.logger.info("**********Starting Alert Trader**********") + + symbolList = self.listSymbol + + count = 1 + + md = {} + prices = {} + curPrice = {} + for symbol in symbolList: + try: + md[symbol] = marketData(self.logger, symbol, sector) + current_date = datetime.now().strftime('%Y-%m-%d') + num_trading_days_back = 30 + result_date = md[symbol].get_trading_days_back(current_date, num_trading_days_back) + prices[symbol] = md[symbol].fetch_market_data("1d", datetime.strptime(result_date, "%Y-%m-%d").date(), datetime.strptime(current_date, "%Y-%m-%d").date()) + curPrice[symbol] = md[symbol].get_current_price() + print(f"{count}/{len(symbolList)}") + self.logger.info(f"{count}/{len(symbolList)}") + count += 1 + except Exception as e: + self.logger.error(f"Error in: {symbol} with error... {str(e)}") + + strategy = momentum(symbolList, self.logger, prices) + symbols = strategy.next(curPrice) + signal = strategy.getSignal() + + result = {} + + for symbol in symbols: + result[symbol] = curPrice[symbol] + + self.alert.emailMomentum("Trivex Momentum Alert Signal !!!", signal, result) + self.logger.info("**********Finishing Alert Trader**********") \ No newline at end of file diff --git a/trivex_contract/src/interfaces.cairo b/trivex_contract/src/interfaces.cairo index 263c157..7f05e54 100644 --- a/trivex_contract/src/interfaces.cairo +++ b/trivex_contract/src/interfaces.cairo @@ -1,4 +1,4 @@ -use trivex_contract::starkstructs::{Position, order_book_entry}; +use trivex_contract::starkstructs::{Position, order_book_entry, history_entry}; use starknet::ContractAddress; use trivex_contract::utils::{UserAddress, Amount, TokenAddress}; @@ -11,8 +11,6 @@ pub trait ITrivexAction { fn get_transactions(self: @TContractState, user: UserAddress) -> Array; fn get_all_user_addresses(self: @TContractState) -> Array; fn get_internal_order_book(self: @TContractState) -> Array; - fn run_strategy(ref self: TContractState, strategy: felt252, amount: Amount, token_address: TokenAddress); - fn get_strategy_price(self: @TContractState, strategy: felt252) -> Amount; fn stake(ref self: TContractState, amount: Amount, token_address: TokenAddress); fn unstake(ref self: TContractState, amount: Amount, token_address: TokenAddress); fn get_staked(self: @TContractState, token_address: TokenAddress, user_address: UserAddress) -> Amount; @@ -23,4 +21,10 @@ pub trait ITrivexAction { fn set_available_balance(ref self: TContractState, value: u256); fn update_external_order_book(ref self: TContractState, symbol: felt252, leverage: u128, total_value: u256, action: felt252); fn get_external_order_book(self: @TContractState) -> Array; + fn run_strategy(ref self: TContractState, strategy: felt252, amount: Amount, token_address: TokenAddress); + fn get_strategy_price(self: @TContractState, strategy: felt252) -> Amount; + fn set_strategy(ref self: TContractState, strategy: felt252, amount: Amount, creator_address: UserAddress); + fn get_history(self: @TContractState, user: UserAddress) -> Array; + fn get_all_histories(self: @TContractState) -> Array; + fn get_all_user_addresses_strategy(self: @TContractState) -> Array; } \ No newline at end of file diff --git a/trivex_contract/src/starkstructs.cairo b/trivex_contract/src/starkstructs.cairo index cb1078d..3d09d12 100644 --- a/trivex_contract/src/starkstructs.cairo +++ b/trivex_contract/src/starkstructs.cairo @@ -18,4 +18,11 @@ pub struct order_book_entry { pub symbol: felt252, pub leverage: u128, pub amount: Amount +} + +#[derive(Copy, Serde, Drop, starknet::Store)] +pub struct history_entry { + pub strategy: felt252, + pub amount: Amount, + pub datetime: u64 } \ No newline at end of file diff --git a/trivex_contract/src/trivexaction.cairo b/trivex_contract/src/trivexaction.cairo index 69e4b23..a02e259 100644 --- a/trivex_contract/src/trivexaction.cairo +++ b/trivex_contract/src/trivexaction.cairo @@ -6,7 +6,7 @@ mod TrivexAction { use core::clone::Clone; use trivex_contract::interfaces::ITrivexAction; use starknet::{get_caller_address, ContractAddress, get_contract_address, get_block_timestamp}; - use trivex_contract::starkstructs::{Position, order_book_entry}; + use trivex_contract::starkstructs::{Position, order_book_entry, history_entry}; use trivex_contract::utils::{UserAddress, TokenAddress, Amount}; use trivex_contract::erc20::{IERC20Dispatcher}; use starknet::contract_address_const; @@ -33,7 +33,11 @@ mod TrivexAction { lender_interest_rate: u256, strategy_price: LegacyMap, strategy_creator: LegacyMap, - owner: UserAddress + owner: UserAddress, + history: LegacyMap<(UserAddress, u128), history_entry>, + user_history_counts: LegacyMap, + strategy_addresses: LegacyMap, + strategy_addresses_len: u256, } #[constructor] @@ -264,29 +268,6 @@ mod TrivexAction { entries } - fn run_strategy(ref self: ContractState, strategy: felt252, amount: Amount, token_address: TokenAddress) { - let caller = get_caller_address(); - let creator = self.strategy_creator.read(strategy); - - let fee_part = amount*20/100; - let payout_part = amount*80/100; - - let token: IERC20Dispatcher = IERC20Dispatcher { - contract_address: token_address, - }; - - let contract_addr = get_contract_address(); - let transfer1 = token.transferFrom(caller, contract_addr, fee_part); - assert(transfer1, 'Contract fee transfer failed.'); - - let transfer2 = token.transferFrom(caller, creator, payout_part); - assert(transfer2, 'Creator payout transfer failed.'); - } - - fn get_strategy_price(self: @ContractState, strategy: felt252) -> Amount{ - self.strategy_price.read(strategy) - } - fn stake(ref self: ContractState, amount: Amount, token_address: TokenAddress) { let caller = get_caller_address(); let token = IERC20Dispatcher { contract_address: token_address }; @@ -401,5 +382,106 @@ mod TrivexAction { entries } + + fn run_strategy(ref self: ContractState, strategy: felt252, amount: Amount, token_address: TokenAddress) { + let caller = get_caller_address(); + let creator = self.strategy_creator.read(strategy); + + let fee_part = amount*20/100; + let payout_part = amount*80/100; + + let token: IERC20Dispatcher = IERC20Dispatcher { + contract_address: token_address, + }; + + let contract_addr = get_contract_address(); + let transfer1 = token.transferFrom(caller, contract_addr, fee_part); + assert(transfer1, 'Contract fee transfer failed.'); + + let transfer2 = token.transferFrom(caller, creator, payout_part); + assert(transfer2, 'Creator payout transfer failed.'); + + let count = self.user_history_counts.read(caller); + let history_value = history_entry { + strategy: strategy, + amount: amount, + datetime: get_block_timestamp() + }; + + if count == 0 { + let current_user_count = self.strategy_addresses_len.read(); + self.strategy_addresses.write(current_user_count, caller); + self.strategy_addresses_len.write(current_user_count + 1); + }; + + self.history.write((caller, count), history_value); + self.user_history_counts.write(caller, count + 1); + } + + fn get_strategy_price(self: @ContractState, strategy: felt252) -> Amount{ + self.strategy_price.read(strategy) + } + + fn set_strategy(ref self: ContractState, strategy: felt252, amount: Amount, creator_address: UserAddress) { + let caller = get_caller_address(); + let owner = self.owner.read(); + assert(caller == owner, 'NOT_OWNER'); + + self.strategy_price.write(strategy, amount); + self.strategy_creator.write(strategy, creator_address); + } + + fn get_history(self: @ContractState, user: UserAddress) -> Array { + let count = self.user_history_counts.read(user); + let mut histories = ArrayTrait::new(); + let mut i = 0; + + while i < count { + let history_value = self.history.read((user, i)); + histories.append(history_value); + i = i + 1; + }; + + return histories; + } + + fn get_all_histories(self: @ContractState) -> Array { + let mut all_histories = ArrayTrait::new(); + let total_users = self.strategy_addresses_len.read(); + let mut u = 0; + + while u < total_users { + let user = self.strategy_addresses.read(u); + let count = self.user_history_counts.read(user); + let mut i = 0; + + while i < count { + let history_value = self.history.read((user, i)); + all_histories.append(history_value); + i = i + 1; + }; + + u = u + 1; + }; + + return all_histories; + } + + fn get_all_user_addresses_strategy(self: @ContractState) -> Array { + let length = self.strategy_addresses_len.read(); + let mut addresses = ArrayTrait::new(); + let mut i = 0_u256; + + loop { + if i == length { + break; + } + let addr = self.strategy_addresses.read(i); + addresses.append(addr); + i = i + 1; + }; + + addresses + } } } diff --git a/trivex_frontend/src/App.css b/trivex_frontend/src/App.css index 74b5e05..5f9be69 100644 --- a/trivex_frontend/src/App.css +++ b/trivex_frontend/src/App.css @@ -36,3 +36,42 @@ transform: rotate(360deg); } } + +/* Web3 animated background elements */ +.web3-glow { + position: fixed; + pointer-events: none; + z-index: -1; + border-radius: 50%; + opacity: 0.6; +} + +.web3-glow:nth-child(1) { + top: 20%; + left: 5%; + width: 400px; + height: 400px; + background: radial-gradient(circle, rgba(155, 109, 255, 0.1) 0%, transparent 70%); + animation: float 15s ease-in-out infinite; +} + +.web3-glow:nth-child(2) { + bottom: 10%; + right: 5%; + width: 500px; + height: 500px; + background: radial-gradient(circle, rgba(106, 75, 161, 0.08) 0%, transparent 70%); + animation: float 20s ease-in-out infinite reverse; +} + +@keyframes float { + 0% { + transform: translateY(0) rotate(0deg); + } + 50% { + transform: translateY(-30px) rotate(5deg); + } + 100% { + transform: translateY(0) rotate(0deg); + } +} diff --git a/trivex_frontend/src/App.js b/trivex_frontend/src/App.js index 4a3d95c..e660e58 100644 --- a/trivex_frontend/src/App.js +++ b/trivex_frontend/src/App.js @@ -7,17 +7,30 @@ import SettingPage from "./pages/SettingPage"; import Navbar from "./components/Navbar"; import Footer from "./components/Footer"; import { AppProvider } from './components/AppProvider'; +import './App.css'; const App = () => ( + {/* Web3 animated background elements */} +
+
+
+ - } /> - } /> - } /> - } /> - } /> + } /> + } /> + } /> + } /> + } />