Quant Invests Where the Quant Invests For You!d
Author: Joe Chamoun Mobile: 403-463-8072 Website: quantinvests.com Email: [email protected] LinkedIn: https://ca.linkedin.com/company/quantinvests
App Name: Quant Invests Tagline: Where the Quant Invests For You! Author: Joe Chamoun Contact Number: 403-463-8072 Website: quantinvests.com Email: [email protected] LinkedIn: https://ca.linkedin.com/company/quantinvests Logo:
Front End:
| Quant Invests | [Logo] Where the Quant Invests for You [Investment App Wireframe] | ------------------------------------------------| [Navigation Menu] |
[User Profile] [Settings] [Logout] |
---|
[Sidebar] |
[Parameter Input Form] |
------------- |
- UserName |
- Profile display |
-Starting Capital |
-Risk Tolerance |
- Investment Horizon |
QI’s Custom Multiplier Summation Indicator:
Example of the home page pie charts: side by side
Shows a breakdown of the portfolio allocations in percent. Followed by Details of the variables, forms, routes, and Style within the app: Styling-CSS:
-fonts = Great Vibes for headings and titles Form content:
- Starting Capital
- Risk Tolerance
- Log In
- Register
- Investment Horizon
Backend:
Next is data storage and api retrieval CI, IDX, Div ID, IMO, signals, portfolio allocation, Fibonacci Confluence zones and machine learning.
CI, IDX, Corr:
Run initialize
INSTALL_BASE_PATH="$HOME/local"
cd ~
mkdir build
cd build
[ -f Python-3.11.6.tgz ] || wget https://www.python.org/ftp/python/3.11.6/Python-3.11.6.tgz
tar -zxvf Python-3.11.6.tgz
[ -f sqlite-autoconf-3240000.tar.gz ] || wget https://www.sqlite.org/2018/sqlite-autoconf-3240000.tar.gz
tar -zxvf sqlite-autoconf-3240000.tar.gz
cd sqlite-autoconf-3240000
./configure --prefix=${INSTALL_BASE_PATH}
make
make install
cd ../Python-3.11.6
LD_RUN_PATH=${INSTALL_BASE_PATH}/lib configure
LDFLAGS="-L
pipenv install --dev pip install virtualenv
python -m pip install pip-tools python -m ensurepip --upgrade pip install --upgrade pip pip install virtualenv pip install -r requirements.txt set FLASK_APP app:"app.py" cd source/repos/quantinvests_2025 python3 -m venv env pip install flask c:\Users\joech\source\repos\quantinvests_2025\env\Scripts\activate pip install --upgrade --force-reinstall -r requirements.txt https://download.visualstudio.microsoft.com/download/pr/a099e4b6-a6a8-4d34-bf95-b00739d35bb7/cdad50779717ba0e56caf89a3ba29ab1/dotnet-sdk-7.0.403-win-x64.exe
cd source/repos/quantinvests_2025 pip install virtualenv pip install -r requirements.txt set FLASK_APP app:"app.py" python -m venv env git config core.autocrlf true set env/bin/activate set FLASK_ENV=development set FLASK_DEBUG=1 run_app.bat
@echo off REM Navigate to your project directory cd C:\Users\joech\source\repos\quantinvests_2025 REM Activate the virtual environment call .virtualenvs\quantinvests_2025-clal_mt2\Scripts\activate cd C:\Users\joech\source\repos\quantinvests_2025.devcontainer pip3.11 install nbformat REM Run Flask app flask run @REM pip install --upgrade pip setuptools wheel
Setup.bat @echo off REM Set Flask app set FLASK_APP=app.py REM Set Flask environment variables set FLASK_ENV=development set FLASK_DEBUG=1 REM Navigate to your project directory cd C:\Users\joech\source\repos\quantinvests_2025 REM Create a Python virtual environment python -m venv .virtualenvs\quantinvests_2025-clal_mt2 REM Activate the virtual environment call .virtualenvs\quantinvests_2025-clal_mt2\Scripts\activate
REM Upgrade pip python -m pip install --upgrade pip
REM Install required Python packages pip install -r requirements.txt
REM Check the Python environment python --version pip list
REM Run Flask app flask run
README Quant Quantitative Strategies: Detailed description of your quantitative strategies. Historical Data: Relevant historical financial data for backtesting. Risk Parameters: Your risk tolerance and any specific risk parameters. Investment Universe: The assets or securities you are interested in. Trading Constraints: Any constraints such as transaction costs, liquidity, etc. Performance Metrics: The metrics you want to use to evaluate the performance of the strategy. pip install pyinstaller cd C:\Users\joech\source\repos\quantinvests_2025
REM Activate the virtual environment call .virtualenvs\quantinvests_2025-clal_mt2\Scripts\activate
Navigate to the directory containing your Python script (your_script.py) in the terminal. /myproject /myproject init.py app.py config.py /models init.py user.py portfolio.py transaction.py /forms init.py registration_form.py login_form.py transaction_form.py portfolio_form.py /templates index.html login.html register.html portfolio.html user_portfolio.html disclaimer.html privacy.html contact.html chart.html about.html /tables symbol.html /static /css style.css /js script.js /images symbol.png run.py requirements.txt In this structure:
app.py is your main Flask application script. config.py contains your Flask configuration classes. The models directory contains your SQLAlchemy models. The forms directory contains your Flask-WTF forms. The templates directory contains your Jinja2 templates. The static directory contains your static files, such as CSS, JavaScript, and images. run.py is the script you run to start your Flask application. requirements.txt lists the Python packages that your project depends on. Remember to adjust this structure based on your actual project structure and requirements. Run PyInstaller:
bash pyinstaller --onefile app.py This command tells PyInstaller to create a single executable file (--onefile) from your_script.py.
After running the command, PyInstaller creates a dist directory in the same directory as your script. Inside dist, you'll find your standalone executable file named your_script.exe.
You can now distribute your_script.exe as a PC application. Users can run it on their machine without needing to have Python installed.
Remember to test your executable thoroughly on the target operating system to ensure it works as expected. Also, be aware that complex applications with many dependencies might require additional steps or options with PyInstaller.
ased on the information you've provided, your Flask application seems to have the necessary components. However, a typical Flask application might include the following files and directories:
Templates: A templates directory that contains HTML templates. You've mentioned portfolio.html, register.html, login.html, and index.html, so it seems you have this covered.
Static Files: A static directory that contains static files such as CSS stylesheets, JavaScript files, and images.
Forms: A Python file (e.g., forms.py) that defines WTForms form classes. You've mentioned RegistrationForm and LoginForm, so it seems you have this covered.
Models: A Python file (e.g., models.py) that defines SQLAlchemy model classes. You've mentioned User and Portfolio, so it seems you have this covered.
Blueprints: A Python file (e.g., portfolio.py) that defines a Flask blueprint. You've mentioned portfolio_bp, so it seems you have this covered.
Database: A SQLite database file (e.g., stocks.db). You've mentioned this in your app.py file, so it seems you have this covered.
Main Application File: A Python file (e.g., app.py) that creates the Flask application and defines routes. You've provided this file, so it seems you have this covered.
Requirements File: A requirements.txt file that lists the Python packages your application depends on. This makes it easier for others (or yourself, in the future) to install the necessary packages.
Configuration File: A Python file (e.g., config.py) that contains configuration variables for your application. This can include things like the secret key, database URI, and any third-party API keys.
This project is a financial application that allows users to manage their stock portfolios. It uses Python, SQLAlchemy, and SQLite to create and manage a database of users and their stock portfolios. Features User Management: The application allows the creation of user accounts with a username, hashed password, starting capital, and current capital. Stock Signals: The application reads stock signal data from CSV files. Each stock signal includes a symbol, signal price, sig_div, sig_ci, sig_idx, multiplier, mult_change, and position. Portfolio Management: The application allows users to manage their stock portfolios. Each portfolio includes a user ID, symbol, company, shares, value, cash, time, and running value. Technologies Python: The application is written in Python, a powerful and flexible programming language. SQLAlchemy: SQLAlchemy is a SQL toolkit and Object-Relational Mapping (ORM) system for Python. It provides a full suite of well-known enterprise-level persistence patterns, designed for efficient and high-performing database access. SQLite: SQLite is a C library that provides a lightweight disk-based database. It allows accessing the database using a nonstandard variant of the SQL query language. Pandas: Pandas is a software library for Python used for data manipulation and analysis. It is used in this application to read CSV files and manipulate data frames. Werkzeug: Werkzeug is a comprehensive WSGI web application library. It is used in this application to generate password hashes. How It Works The application first creates a new user and adds the user to the database. It then reads the last 14 periods from the CSV files and converts the data into a list of StockSignal objects. These StockSignal objects are added to the session and committed to the database. The application can then query the database to retrieve the user and their portfolio.
Commit_changes.bat
@echo off REM Navigate to your project directory cd C:\Users\joech\source\repos\quantinvests_2025 REM Commit changes to Git git add . git commit -m "Your commit message: Dec 2023" git push REM Set the upstream branch for the first time git push --set-upstream origin quantinvests_2025 git config --global core.autocrlf true REM Configure Git to automatically set the upstream branch for new branches @REM git config --global push.default current git push --set-upstream origin quantinvests_2025 app.spec
a = Analysis( ['app\app.py'], pathex=[], binaries=[], datas=[], hiddenimports=[], hookspath=[], hooksconfig={}, runtime_hooks=[], excludes=[], noarchive=False, ) pyz = PYZ(a.pure)
exe = EXE( pyz, a.scripts, a.binaries, a.datas, [], name='app', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True, disable_windowed_traceback=False, argv_emulation=False, target_arch=None, codesign_identity=None, entitlements_file=None, ) Importing Our List of Stock Symbols
● The first thing we need to do is import the constituents of the stocks and markets. ● These constituents change over time, so in an ideal world you would connect directly to the index provider (Standard & Poor's) and pull their real-time constituents on a regular basis. ● Currently, filtered and sorted 955 symbols, need further categorize them into type(ie. Etfs, benchmarks or dependants ● Symbol List, Sector w/ underlying companies symbols and stats As of 2-6-2022 here is a list of the companies being considered:
['A','AA','AAL','AAP','AAPL','ABBV','ABC','ABMD','ABT','ACC','ACGL','ACHC','ACM','ACN','ADBE','ADI','ADM','ADNT','ADP','ADS','ADSK','ADT','AEE','AEP','AES','AFG','AFL','AGCO','AGIO','AGNC','AGO','AGR','AIG','AIV','AIZ','AJG','AKAM','AL','ALB','ALGN','ALK','ALKS','ALL','ALLE','ALLY','ALNY','ALSN','AMAT','AMCR','AMCX','AMD','AME','AMG','AMGN','AMH','AMP','AMT','AMZN','AN','ANAT','ANET','ANSS','ANTM','AON','AOS','APA','APD','APH','APLE','APTV','AR','ARE','ARMK','ARNC','ARW','ASB','ASH','ASML','ATH','ATO','ATR','ATVI','AVB','AVGO','AVT','AVY','AWI','AWK','AXP','AXS','AXTA','AYI','AZO','AZPN','BA','BAC','BAH','BAX','BBY','BC','BDN','BDX','BEN','BERY','BFAM','BG','BGCP','BHF','BIG','BIIB','BIO','BJ','BK','BKI','BKNG','BKR','BKU','BLD','BLK','BLL','BLUE','BMRN','BMY','BOH','BOKF','BPOP','BR','BRKR','BRO','BRX','BSX','BURL','BWA','BWXT','BXP','BYND',‘C','CABO','CACC','CACI','CAG','CAH','CARR','CASY','CAT','CB','CBOE','CBRE','CBSH','CBT','CC','CCI','CCK','CCL','CDAY','CDEV','CDK','CDNS','CDW','CE','CERN','CF','CFG','CFR','CFX','CGNX','CHD','CHE','CHH','CHK','CHTR','CHWY','CI','CIM','CINF','CIT','CL','CLH','CLR','CLX','CMA','CMCSA','CME','CMG','CMI','CMS','CNA','CNC','CNDT','CNK','CNP','CNQ','CNX','COF','COLM','COMM','CONE','COO','COP','COR','COST','COTY','CPA','CPB','CPRI','CPRT','CPT','CR','CRI','CRL','CRM','CSCO','CSGP','CSL','CSX','CTAS','CTLT','CTSH','CTVA','CTXS','CUBE','CVS','CVX','CW','CXP','CZR','D','DAL','DCI','DD','DE','DEI','DELL','DFS','DG','DGX','DHC','DHI','DHR','DIS','DISCA','DISCK','DISH','DKS','DLB','DLR','DLTR','DNB','DOCU','DOV','DOW','DOX','DPZ','DRE','DRI','DTE','DUK','DVA','DVN','DXC','DXCM','EA','EAF','EBAY','ECL','ED','EEFT','EFX','EHC','EIX','EL','ELS','EMN','EMR','ENR','EOG','EPAM','EPR','EQC','EQH','EQIX','EQR','EQT','ERIE','ES','ESI','ESRT','ESS','ETN','ETR','ETSY','EVBG','EVR','EVRG','EW','EWBC','EXAS','EXC','EXEL','EXP','EXPD','EXPE','EXR','F','FAF','FANG','FAST','FB','FBHS','FCNCA','FCX','FDS','FDX','FE','FFIV','FHB','FHN','FICO','FIS','FISV','FITB','FL','FLO','FLR','FLS','FLT','FMC','FNB','FND','FNF','FOX','FOXA','FRC','FRT','FSLR','FTI','FTNT','FTV','FWONA','FWONK','G','GD','GDDY','GDX','GE','GGG','GHC','GILD','GIS','GL','GLD','GLPI','GLW','GM','GNTX','GOOG','GOOGL','GPC','GPK','GPN','GPS','GRUB','GS','GT','GTES','GWRE','GWW','H','HAIN','HAL','HAS','HBAN','HBI','HCA','HD','HE','HEI','HES','HFC','HGV','HHC','HIG','HII','HIW','HLF','HLT','HOG','HOOD','HOLX','HON','HP','HPE','HPP','HPQ','HRB','HRC','HRL','HSIC','HST','HSY','HTA','HUBB','HUM','HUN','HXL','IAC','IART','IBKR','IBM','ICE','ICUI','IDXX','IEX','IFF','IGT','ILMN','INCY','INFO','INGR','INTC','INTU','INVH','IONS','IP','IPG','IPGP','IQV','IR','IRM','ISRG','IT','ITB','ITT','ITW','IVZ','IWM','IYT','J','JAZZ','JBGS','JBHT','JBL','JBLU','JCI','JEF','JKHY','JLL','JNJ','JNPR','JPM','JWN','K','KAR','KBE','KDP','KEX','KEY','KEYS','KHC','KIM','KLAC','KMB','KMI','KMX','KNX','KO','KOS','KR','KRC','KSS','KSU','L','LAMR','LAZ','LBRDA','LBRDK','LDOS','LEA','LECO','LEG','LEN','LFUS','LH','LHX','LII','LIN','LKQ','LLY','LMT','LNC','LNG','LNT','LOPE','LOW','LPLA','LRCX','LSI','LSTR','LSXMA','LSXMK','LULU','LUMN','LUV','LVS','LW','LYB','LYFT','LYV','M','MA','MAA','MAC','MAN','MANH','MAR','MAS','MASI','MAT','MCD','MCHP','MCK','MCO','MCY','MD','MDLZ','MDT','MDU','MET','MFA','MGM','MHK','MIC','MIDD','MKC','MKL','MKSI','MKTX','MLM','MMC','MMM','MNST','MO','MOH','MORN','MOS','MPC','MPW','MPWR','MRK','MRNA','MRO','MRVL','MS','MSCI','MSFT','MSI','MSM','MTB','MTCH','MTD','MTN','MU','MUR','NATI','NAVI','NBIX','NBR','NCLH','NCR','NDAQ','NDSN','NEE','NEM','NEU','NFG','NFLX','NI','NKE','NKTR','NLOK','NLSN','NLY','NNN','NOC','NOV','NOW','NRG','NRZ','NSC','NTAP','NTNX','NTRS','NUAN','NUE','NUS','NVDA','NVR','NVT','NWL','NWS','NWSA','NXPI','NYCB','O','OC','ODFL','OFC','OGE','OHI','OI','OKE','OKTA','OLED','OLLI','OLN','OMC','OMF','ON','ORCL','ORI','ORLY','OSK','OTIS','OUT','OXY','OZK','PACW','PAG','PANW','PAYC','PAYX','PB','PBCT','PBF','PCAR','PCG','PEAK','PEG','PEGA','PEN','PEP','PETS','PFE','PFG','PG','PGR','PGRE','PH','PHM','PII','PINC','PK','PKG','PKI','PLD','PM','PNC','PNFP','PNR','PNW','PODD','POOL','POST','PPC','PPG','PPL','PRGO','PRU','PSA','PSTG','PSX','PTC','PTEN','PVH','PWR','PXD','PYPL','QCOM','QGEN','QQQ','QRTEA','QRVO','R','RAD','RCL','RE','REG','REGN','RES','RF','RGA','RGLD','RHI','RIG','RJF','RL','RLGY','RMD','RNG','RNR','ROK','ROL','ROP','ROST','RPM','RRC','RS','RSG','RTX','RWR','RYN','SABR','SAGE','SATS','SBAC','SBNY','SBUX','SC','SCCO','SCHW','SCI','SEB','SEE','SEIC','SFM','SGEN','SHW','SIRI','SITC','SIVB','SIX','SJM','SKX','SLB','SLG','SLGN','SLM','SLV','SM','SMG','SNA','SNDR','SNPS','SNV','SO','SON','SOXX','SPB','SPG','SPGI','SPLK','SPR','SPY','SQ','SRC','SRCL','SRE','SRPT','SSNC','ST','STE','STL','STLD','STOR','STT','STWD','STX','STZ','SUI','SVC','SWCH','SWK','SWKS','SYF','SYK','SYY','T','TAP','TCBI','TDC','TDG','TDOC','TDS','TDY','TEAM','TECH','TEL','TER','TEX','TFC','TFSL','TFX','TGT','THG','THO','THS','TJX','TKR','TLT','TMO','TMUS','TOL','TPR','TPX','TREX','TRGP','TRIP','TRMB','TRN','TROW','TRU','TRV','TSCO','TSLA','TSN','TTC','TTWO','TWLO','TWO','TWOU','TWTR','TXN','TXT','TYL','UA','UAA','UAL','UBER','UDR','UFS','UGI','UHAL','UHS','UI','ULTA','UMPQ','UNH','UNIT','UNM','UNP','UNVR','UPS','URBN','URI','USB','USFD','USM','USO','UTHR','UUP','V','VC','VEEV','VFC','VIAC','VIACA','VICI','VIRT','VLO','VMC','VMI','VMW','VNO','VOYA','VRSK','VRSN','VRTX','VST','VTR','VVV','VXX','VZ','W','WAB','WAL','WAT','WBA','WBS','WBT','WCC','WDAY','WDC','WEC','WELL','WEN','WEX','WFC','WH','WHR','WLK','WLL','WLTW','WM','WMB','WMT','WPC','WRB','WRK','WSM','WSO','WST','WTFC','WTM','WTRG','WU','WY','WYNN','X','XBI','XEL','XHB','XLB','XLC','XLE','XLF','XLI','XLK','XLNX','XLP','XLU','XLV','XLY','XOM','XPO','XRAY','XRT','XRX','XYL','Y','YUM','YUMC','Z','ZBH', 'ZBRA','ZEN','ZG','ZION','ZNGA','ZTS']
Identify Stockcycle:
--------------------
1) If the Stock's Cycle is Trending
- the absolute value of the CI has to be greater than 20
2) If the Stock's Cycle is Congestion Index
- the absolute value of the CI has to be less than 20,
- separate them from the stocks experiencing congestion in price Action
C = Closing Price
X = Time Segment
H = Highest High for the chosen Time Period
L = Lowest Low for the chosen Time Period
Noise minimization = Further Smoothed by a 3 Day EMA
Index Fluctuations & Range of Readings:
--------------------------------------
Range is from 100 to -100
Trending instrument's CI reading must be great than 20 for a long position
less than -20 indicates a downturn in the instrument, short position
List of Filtered/Usable Trending Ticker Symbols
"""
""" Trend Identification Congestion Index: +/-20 reading indicates market is trending (otherwise sideways/congested price action.
C= Closing price, X=Time, H=Highest high for the time period, L= Lowest low. To minimize noise, add an additional 3 day EMA. (optional).
Python Code:
def congestion_index(df, window): col = 'CI_' + str(window) df['HH'] = df['High'].rolling(window=window).max() df['LL'] = df['Low'].rolling(window=window).min() df['ROC'] = (df['Close'] - df.Close[-window]) / df.Close[-window] df['Div'] = (df['HH'] - df['LL']) / df['LL'] df[col] = df['ROC']/df['Div'] return df[col].ewm(span=3, adjust=False, min_periods=3, ignore_na=True).mean()
Excel Formula: HH(E)=MAX (B22:B49) B=high column LL(F)=MIN (C22:C49) C=Low Column ROC(G)=(D49-D22)/D22*100 D=Close Column (HH-LL)/LL (H)=(E49-F49)/(f49+0.01) CI (I)=G49/H49 DX
def IDX(df, window): col = 'IDX_' + str(window) HH = df.High.rolling(window=window).max() LL = df.Low.rolling(window=window).min() df[col] = ((df.Close - LL)*100) / (HH-LL) df = pd.DataFrame(df[col]) return df[col].ewm(span=3, adjust=False, min_periods=3, ignore_na=True).mean() Intermarket Momentum Indicator
Indicator Oscillator
--------------------
1) If the Indicator has reached a peak above 80 and then falls below 80
- A Short signal is generated
2) If the Indicator has reached a trough below 20 and then rises above 20
- the absolute value of the CI has to be less than 20,
- separate them from the stocks experiencing congestion in price Action
I = Indicator current value
X = Time Segment
H = Highest indicator High for the chosen Time Period
L = Lowest indicator Low for the chosen Time Period
Noise minimization = Further Smoothed by a 3 Day EMA
Index Fluctuations & Range of Readings:
--------------------------------------
Range is from 100 to 0
Trending instrument's IMO reading must be less than 20 at n-1 & great than 20 at n
for a long position
Trending instrument's IMO reading must be great than 80 at n-1 & then less than 80
at n period to qualify for a short position
List of Filtered/Usable Trending Ticker Symbols
def IMO(indicator, window): cols = [] col = 'IMO_' + str(indicator) + str(window) HH = indicator.rolling(window=window).max() LL = indicator.rolling(window=window).min() df = pd.DataFrame(index=indicator.index) df[col] = ((indicator - LL)*100) / (HH-LL) cols.append(col) return df[cols].ewm(span=3, adjust=False, min_periods=3, ignore_na=True).mean()
Quant You can explain the starting portfolio to the user as follows:
The portfolio consists of various stocks, each represented by a symbol. For example, 'AAPL' represents Apple Inc.
The 'Price' column shows the current price of each stock.
The 'Signal_div', 'Signal_idx', 'Signal_ci', 'Signal_ds', and 'Signal_cor' columns represent different signals or indicators that might influence your decision to buy or sell the stock. The meaning of these signals depends on your specific trading strategy.
The 'Mult_change' column represents the change in the multiplier, which is a factor that determines how much money you want to invest in each stock.
The 'Multiplier' column represents the current multiplier for each stock. The multiplier directly influences the number of shares you hold for each stock. The higher the multiplier, the more shares you hold.
The 'Shares' column (which you calculated based on the price and the multiplier) represents the number of shares you currently hold for each stock.
The value of your portfolio is the sum of the value of all shares you hold. You can calculate the value of each stock by multiplying the number of shares by the current price, and then sum up these values to get the total value of your portfolio.
Please note that this is a simplified explanation. The actual details might vary depending on your specific trading strategy and the meaning of the signals and the multiplier in your strategy.
from dotenv import load_dotenv import os
load_dotenv("C:/workspaces/Congestion/hourly/.github/.env") import time import yfinance as yf import pandas as pd import numpy as np import commons from commons import * import matplotlib.pyplot as plt #%% symbols = commons.short_list windows = commons.windows style = matplotlib.style.use('dark_background') plt.style.use('dark_background')
plt_io.templates["custom_dark"] = plt_io.templates["plotly_dark"]
plt_io.templates["custom_dark"]['layout']['paper_bgcolor'] = '#30404D' plt_io.templates["custom_dark"]['layout']['plot_bgcolor'] = '#30404D'
plt_io.templates['custom_dark']['layout']['yaxis']['gridcolor'] = '#4f687d' plt_io.templates['custom_dark']['layout']['xaxis']['gridcolor'] = '#4f687d'
sns.set_style('whitegrid') class CongestionIndexTrader: def init(self, symbol, start, now, interval, windows): self.symbol = symbol self.start = start self.now = now self.interval = interval self.windows = windows self.df = None
def IMO_function(self, indicator, n):
LL = indicator.rolling(window=n).min()
HH = indicator.rolling(window=n).max()
IMO_val = (indicator - LL) / (HH - LL) * 100
return IMO_val.ewm(span=2, min_periods=3).mean()
def signal_gen(self, IMO_df):
Trade_ID = np.where(
((IMO_df < 75) & (IMO_df.shift(1) > 75)) | (IMO_df < 25), -1, 0)
Trade_ID = np.where(
((IMO_df > 25) & (IMO_df.shift(1) < 25)) | (IMO_df > 75), 1, Trade_ID)
return Trade_ID
def calculate_window_indicators(self):
for window in self.windows:
HH = self.df['High'].rolling(window=window).max()
LL = self.df['Low'].rolling(window=window).min()
CI = self.df['Close'].pct_change(window) / (HH.pct_change(window) + 1e-9) * 100
IDX = (self.df['Close'] - LL) / (HH - LL) * 100
self.df[f'CI_{window}'] = CI
self.df[f'IDX_{window}'] = IDX
self.df[f'CI_IMO_{window}'] = self.IMO_function(CI, window)
self.df[f'IDX_IMO_{window}'] = self.IMO_function(IDX, window)
self.df[f'CI_signal_{window}'] = self.signal_gen(self.df[f'CI_IMO_{window}'])
self.df[f'IDX_signal_{window}'] = self.signal_gen(self.df[f'IDX_IMO_{window}'])
self.df[f'CI_trend_{window}'] = np.where(CI > 20, "Bullish", np.where(CI < -20, "Bearish", "Congested"))
self.df[f"ROC_{window}"] = ((self.df.Close - self.df.Close[-window]) / self.df.Close[-window]) * 100
std = self.df['Close'].rolling(window=window, min_periods=5).std()
mid_band = self.df['Close'].rolling(window=window, min_periods=5).mean()
ATR = self.df['TR'].rolling(window=window).mean()
DS = ((self.df['Close'] - mid_band)/mid_band) * 100
ID = ((self.df['Close']-mid_band) + (2*std))/(4*std)
self.df[f'std_{window}'] = std
self.df[f'mid_band_{window}'] = mid_band
self.df[f'upper_band_{window}'] = mid_band + 2*std
self.df[f'lower_band_{window}'] = mid_band - 2*std
self.df[f'ATR_{window}'] = ATR
self.df[f'lower_keltner_{window}'] = mid_band - (ATR * 1.5)
self.df[f'upper_keltner_{window}'] = mid_band + (ATR * 1.5)
self.df[f'DS_{window}'] = DS.ewm(span=3, adjust=False).mean()
self.df[f'ID_{window}'] = ID.ewm(span=3, adjust=False).mean()
def snapshot(self):
self.df = yf.download(self.symbol, start=self.start, end=self.now, interval=self.interval)
self.df['date'] = self.df.index
self.df['returns'] = np.log(self.df['Adj Close'] / self.df['Adj Close'].shift(1))
self.df['log_returns'] = np.log(self.df['Close'] / self.df['Close'].shift(1))
self.df['TR'] = abs(self.df['High'] - self.df['Low'])
self.calculate_window_indicators()
return self.df.fillna(0)
def plot_trends_and_signals(self, window):
# Ensure the DataFrame is not empty
if self.df is None or self.df.empty:
print("DataFrame is empty. No data to plot.")
return
# Slice the DataFrame to the last 'slice_' rows
slice_ = 255
df_slice = self.df[-slice_:]
# Calculate the buffer for y-axis limits
buffer_percent = 0.05 # 5% buffer above and below the price range
price_min = df_slice['Close'].min()
price_max = df_slice['Close'].max()
price_buffer = (price_max - price_min) * buffer_percent
# Plot the closing price
# Save the figure and axis reference
fig, ax = plt.subplots(figsize=(14, 7))
ax.plot(df_slice.index, df_slice['Close'],
label='Closing Price', color='skyblue')
# Plot CI_signal as markers
ci_long_signals = df_slice[df_slice[f'CI_signal_{window}'] > 0]
ci_short_signals = df_slice[df_slice[f'CI_signal_{window}'] < 0]
ax.scatter(ci_long_signals.index,
ci_long_signals['Close'], label='CI Long Signal', marker='^', color='lime')
ax.scatter(ci_short_signals.index,
ci_short_signals['Close'], label='CI Short Signal', marker='v', color='red')
# Plot IDX_signal as markers
idx_long_signals = df_slice[df_slice[f'IDX_signal_{window}'] > 0]
idx_short_signals = df_slice[df_slice[f'IDX_signal_{window}'] < 0]
ax.scatter(idx_long_signals.index,
idx_long_signals['Close'], label='IDX Long Signal', marker='o', color='aqua', alpha=0.5)
ax.scatter(idx_short_signals.index,
idx_short_signals['Close'], label='IDX Short Signal', marker='x', color='fuchsia', alpha=0.5)
# Highlight CI_trend areas with more opaque colors
bullish_trend = df_slice[df_slice[f'CI_trend_{window}'] == 'Bullish']
bearish_trend = df_slice[df_slice[f'CI_trend_{window}'] == 'Bearish']
congested_trend = df_slice[df_slice[f'CI_trend_{window}'] == 'Congested']
# Plot bullish trend areas
ax.fill_between(
bullish_trend.index, bullish_trend['Close'], color='green', alpha=0.3, label='Bullish Trend')
# Plot bearish trend areas
ax.fill_between(
bearish_trend.index, bearish_trend['Close'], color='red', alpha=0.5, label='Bearish Trend')
# Plot congested trend areas
ax.fill_between(congested_trend.index,
congested_trend['Close'], color='orange', alpha=0.3, label='Congested Trend')
# Customize and show the plot
ax.set_title(
f'Closing Price with CI and IDX Signals for {self.symbol}')
ax.set_xlabel('Date')
ax.set_ylabel('Price')
ax.legend()
# Set y-axis limits with buffer
ax.set_ylim(price_min - price_buffer, price_max + price_buffer)
# Save the figure
chart_filename = f'/workspaces/Congestion/hourly/charts/trading_chart_{self.symbol}.jpg'
fig.savefig(chart_filename)
plt.close(fig) # Close the figure to free up memory
"""Plot"""
now = datetime.datetime.now() start_daily = now - datetime.timedelta(days=2500) start_hourly = now - datetime.timedelta(days=720) start_quarter = now - datetime.timedelta(days=80)
plt.style.use('dark_background')
best_windows_df = pd.DataFrame( columns=['Symbol', 'Best Window', 'Performance']) windows = commons.windows
for symbol in short_list: # Initialize the trader with the necessary parameters trader = CongestionIndexTrader( symbol=symbol, start=start_hourly, now=now, interval='1h', windows=windows)
# Download the data and calculate indicators
df_snapshot = trader.snapshot()
df = pd.DataFrame(df_snapshot)
# Plot trends and signals
# Use the first window size for plotting
trend_path = f"C:/workspaces/Congestion/hourly/tables/{symbol}.csv"
df.to_csv(trend_path)
# Assuming this method exists in your class
trader.plot_trends_and_signals(window=40)
DIVERGENCE
Bollinger Band Basics Ags Calculations
import cProfile from commons import table_path import os import commons from commons import * import datetime
import pandas as pd
symbols = commons.short_list
now = datetime.datetime.now() start_hourly = now - datetime.timedelta(days=720)
warnings.filterwarnings('ignore')
plt.style.use('dark_background')
def IMO_function(indicator, n): LL_200 = indicator.rolling(window=n).min() HH_200 = indicator.rolling(window=n).max() IMO_val = (indicator - LL_200)*100 / (HH_200-LL_200)
return IMO_val.ewm(span=2, min_periods=3).mean()
def reverse_signal_gen(Signal_ID_data): Trade_ID = np.where(((Signal_ID_data < 75) & ( Signal_ID_data.shift(1) > 75)) | (Signal_ID_data < 25), 1, 0)
Trade_ID = np.where(((Signal_ID_data > 25) & (Signal_ID_data.shift(1) < 25)) | (
Signal_ID_data > 75), -1, Trade_ID)
return Trade_ID
def signal_gen(Signal_ID_data): Trade_ID = np.where(((Signal_ID_data < 75) & ( Signal_ID_data.shift(1) > 75)) | (Signal_ID_data < 25), -1, 0)
Trade_ID = np.where(((Signal_ID_data > 25) & (Signal_ID_data.shift(1) < 25)) | (
Signal_ID_data > 75), 1, Trade_ID)
return Trade_ID
def figures_to_html(figs, filename="dashboard.html"): dashboard = open(filename, 'w') dashboard.write("" + "\n") for fig in figs: inner_html = fig.to_html().split('')[1].split('')[0] dashboard.write(inner_html)
DIVERGENCE STRATEGIES: The selected Python code is part of a script for a trading strategy based on divergence indices. It uses the pandas library for data manipulation and plotly for visualization. The script is divided into several parts:
- Imports and setup: The script imports necessary libraries and sets up some variables. It also sets the style for any plots to 'dark_background'.
- Function definitions: Two functions are defined: o figures_to_html(figs, filename="dashboard.html"): This function takes a list of plotly figures and a filename, and writes the figures to an HTML file. o DivergenceIndexTrader: This is a class that encapsulates the trading strategy. It has several methods: init(self, start, now, interval, windows): The constructor sets up the trader with a start and end time, an interval, and a window size. get_data(self, symbol): This method reads a CSV file for a given symbol into a pandas DataFrame. IMO_function(self, indicator, n): This method calculates the IMO (Index of Market Overbought/Oversold) value for a given indicator and window size. reverse_signal_gen(self, Signal_ID_data) and signal_gen(self, Signal_ID_data): These methods generate trading signals based on the IMO values. main(self, df_dep, df_ben, dependant, benchmark, n): This method calculates several divergence indices and trading signals for a given dependant and benchmark, and adds them to the dependant's DataFrame.
- Main script: The main part of the script initializes a DivergenceIndexTrader and uses it to calculate divergence indices and trading signals for a list of symbols against a list of benchmarks. The results are saved to CSV files.
Hourly Divergence.py file:
import plotly.io as py import plotly.graph_objects as go import cProfile from commons import table_path import os import commons from commons import * import datetime
import pandas as pd
symbols = commons.short_list
now = datetime.datetime.now() start_hourly = now - datetime.timedelta(days=720)
warnings.filterwarnings('ignore')
plt.style.use('dark_background')
def figures_to_html(figs, filename="dashboard.html"): dashboard = open(filename, 'w') dashboard.write("" + "\n") for fig in figs: inner_html = fig.to_html().split('')[1].split('')[0] dashboard.write(inner_html)
class DivergenceIndexTrader: def init(self, start, now, interval, windows): self.start = start self.now = now self.interval = interval self.windows = windows self.data = {}
def get_data(self, symbol):
trend_path = f"C:/workspaces/Congestion/hourly/tables/{symbol}.csv"
df = pd.read_csv(trend_path, index_col='Datetime', parse_dates=True)
self.data = pd.DataFrame(df)
return self.data
def IMO_function(self, indicator, n):
LL_200 = indicator.rolling(window=n).min()
HH_200 = indicator.rolling(window=n).max()
IMO_val = (indicator - LL_200)*100 / (HH_200-LL_200)
return IMO_val.ewm(span=2, min_periods=3).mean()
def reverse_signal_gen(self, Signal_ID_data):
Trade_ID = np.where(((Signal_ID_data < 75) & (
Signal_ID_data.shift(1) > 75)) | (Signal_ID_data < 25), 1, 0)
Trade_ID = np.where(((Signal_ID_data > 25) & (Signal_ID_data.shift(1) < 25)) | (
Signal_ID_data > 75), -1, Trade_ID)
return Trade_ID
def signal_gen(self, Signal_ID_data):
Trade_ID = np.where(((Signal_ID_data < 75) & (
Signal_ID_data.shift(1) > 75)) | (Signal_ID_data < 25), -1, 0)
Trade_ID = np.where(((Signal_ID_data > 25) & (Signal_ID_data.shift(1) < 25)) | (
Signal_ID_data > 75), 1, Trade_ID)
return Trade_ID
def main(self, df_dep, df_ben, dependant, benchmark, n):
corr = df_ben[f'ROC_{n}'].rolling(n).corr(df_dep[f'ROC_{n}'])
corr_ewm = corr.ewm(span=3, min_periods=3).mean()
DIV_ID = df_ben[f'ID_{n}']-df_dep[f'ID_{n}']
ID = DIV_ID.divide(df_dep[f'ID_{n}']) * 100
DS = df_dep[f'DS_{n}'] - df_ben[f'DS_{n}']
df_dep[f'Signal_DS_{benchmark}_{n}'] = np.multiply(DS, corr_ewm)
df_dep[f'Signal_ID_{benchmark}_{n}'] = np.multiply(ID, corr_ewm)
df_dep[f'IMO_ID_{benchmark}_{n}'] = self.IMO_function(
df_dep[f'Signal_ID_{benchmark}_{n}'], n)
df_dep[f'IMO_DS_{benchmark}_{n}'] = self.IMO_function(
df_dep[f'Signal_DS_{benchmark}_{n}'], n)
df_dep[f'IMO_corr_{benchmark}_{n}'] = self.IMO_function(corr_ewm, n)
df_dep[f'Trade_ID_{benchmark}_{n}'] = self.reverse_signal_gen(
df_dep[f'IMO_ID_{benchmark}_{n}'])
df_dep[f'Trade_DS_{benchmark}_{n}'] = self.reverse_signal_gen(
df_dep[f'IMO_DS_{benchmark}_{n}'])
df_dep[f'Trade_corr_{benchmark}_{n}'] = self.signal_gen(
df_dep[f'IMO_corr_{benchmark}_{n}'])
return df_dep[[f'Trade_corr_{benchmark}_{n}', f'Trade_DS_{benchmark}_{n}', f'Trade_ID_{benchmark}_{n}']]
%%
divergence_trader = DivergenceIndexTrader(start_hourly, now, "1h", windows=40)
benchmark_data = {}
for benchmark in commons.benchmarks: benchmark_data[benchmark] = divergence_trader.get_data(benchmark)
for symbol in symbols: print(f"Processing symbol: {symbol}") dependant_data = divergence_trader.get_data(symbol) results = []
# Loop over each benchmark
for benchmark in commons.benchmarks:
divergence_result = divergence_trader.main(
dependant_data, benchmark_data[benchmark], symbol, benchmark, 40)
results.append(divergence_result)
# Concatenate results
df_results = pd.concat(results, axis=1)
# Concatenate results with dependant_data
df_final = pd.concat([dependant_data, df_results], axis=1)
# Save to a CSV file
table_path = f"C:/workspaces/Congestion/hourly/signals/{symbol}.csv"
df_final.to_csv(table_path)
""" Loop over each symbol in symbols. For each symbol, it will get the data for that symbol and store it in dependant. It will then loop over each benchmark in commons.benchmarks. For each benchmark, it will get the data for that benchmark and store it in bench_mark. It will then calculate the divergence between dependant and bench_mark using the main method, and append the result to the results list. After looping over all benchmarks, it will concatenate all the results into a single DataFrame df. It will then save df to a CSV file in the C:/workspaces/Congestion/hourly/signals/ directory, with the filename being the symbol name.
In this revised class:
The calculate_window_indicators method is now properly defined within the class and is responsible for calculating the indicators for each window size. The snapshot method has been updated to call calculate_window_indicators for each window size. The string formatting for dynamic window size in DataFrame column names has been corrected (replaced %7Bwindow%7D with {window}). The backtest and analyze_trade_windows methods remain unchanged and should be included in the class as well. Make sure to include the backtest and analyze_trade_windows methods in the class if they are not already there. The usage example demonstrates how to use the class to perform a snapshot, backtest, and analyze the trade windows.
The init method initializes the class with the stock symbol, start and end dates, interval, and window sizes for the analysis. The IMO_function method calculates the Inertia/Momentum Oscillator (IMO) value for a given indicator and window size. The signal_gen method generates trading signals based on the IMO values. The snapshot method downloads the stock data using yfinance, calculates various metrics, and applies the CI and IMO calculations for each window size.
By using a class, you encapsulate all related functionality, making the code more organized and easier to maintain. You can also easily extend the
- We import the necessary modules and classes.
- We set the
rel_path
to the directory where the data is stored. - We instantiate the
DivergenceIndexTrader
class with the appropriate parameters. - We call the
diverge
method to calculate divergence for the specified ticker. - We backtest the strategy using the
backtest
method. - If the
trade_log_df
DataFrame is not empty, we analyze the trade windows and print the results. - We identify the most profitable window based on the total profit/loss and print it.
Please ensure that the commons
module and the CongestionIndexTrader
class are correctly defined and imported. Also, make sure that the rel_path
points
to the correct location of your data files. The placeholders for the curly braces have been corrected to {}
in the print statement.
"""
Flask APP:
Quant Invests Where the Quant Invests For You! Author: Joe Chamoun Mobile: 403-463-8072 Website: quantinvests.com Email: [email protected] LinkedIn: https://ca.linkedin.com/company/quantinvests ======================================================== Details of the investment service app: ============================================= App Name: Quant Invests Tagline: Where the Quant Invests For You! Author: Joe Chamoun Contact Number: 403-463-8072 Website: quantinvests.com Email: [email protected] LinkedIn: https://ca.linkedin.com/company/quantinvests Logo: Front End: | Quant Invests | [Logo] Where the Quant Invests for You [Investment App Wireframe] | ------------------------------------------------| [Navigation Menu] | | [User Profile] [Settings] [Logout] | |----------------------------------------------| | [Sidebar] | Main Content Area | | [Parameter Input Form] | | |-------------|--------------------------------| |- UserName | Login |- Profile display | [Submit Button] | -Starting Capital |[Pie Table Bullish Positions by percent] | -Risk Tolerance |[Pie Table Bearish Positions by percent] | |- Investment Horizon | |- register | | | | | | [Recommendation Area] | | | - QI’s Portfolio Breakdown | | | - Performance Charts | | | - Custom Multiplier Chart QI’s Custom Multiplier Summation Indicator: provide a flask app that can provide the front end Copilot To create a Flask app that serves as the frontend for your investment service application, you’ll need to set up a Flask project with the necessary routes, templates, and static files. Here’s a blueprint to get you started:
- Project Structure: o Organize your project into directories for templates, static files, and the main application.
- QuantInvestsApp/
- ├── app/
- │ ├── templates/
- │ │ ├── base.html
- │ │ ├── index.html
- │ │ └── dashboard.html
- │ ├── static/
- │ │ ├── css/
- │ │ ├── js/
- │ │ └── images/
- │ ├── init.py
- │ ├── routes.py
- │ └── forms.py
- ├── config.py
- ├── run.py
- Flask Application Setup (init.py): o Initialize your Flask app and configure it. Python from flask import Flask
def create_app(): app = Flask(name) # Additional configuration if needed
from . import routes
app.register_blueprint(routes.bp)
return app
AI-generated code. Review and use carefully. More info on FAQ. 18. Routes (routes.py): o Define the routes for your application. Python from flask import Blueprint, render_template
bp = Blueprint('main', name)
@bp.route('/') def index(): return render_template('index.html')
@bp.route('/dashboard') def dashboard(): return render_template('dashboard.html') AI-generated code. Review and use carefully. More info on FAQ. 19. Templates: o Create HTML templates using Jinja2 syntax. o base.html will contain the common layout for your app. o index.html and dashboard.html will extend base.html and contain specific content for each page. 20. Static Files: o Place CSS, JavaScript, and image files in the static directory. o Link to these files in your HTML templates to style your frontend and add interactivity. 21. Forms (forms.py, optional): o If your app requires user input, define Flask-WTF forms. Python from flask_wtf import FlaskForm from wtforms import StringField, SubmitField
class InvestmentForm(FlaskForm): starting_capital = StringField('Starting Capital') risk_tolerance = StringField('Risk Tolerance') investment_horizon = StringField('Investment Horizon') submit = SubmitField('Submit') AI-generated code. Review and use carefully. More info on FAQ. 22. Run the Application (run.py): o Create a script to run your Flask app. Python from app import create_app
app = create_app()
if name == 'main': app.run(debug=True) AI-generated code. Review and use carefully. More info on FAQ. 23. Dependencies: o Ensure you have Flask and Flask-WTF installed. o Use a requirements.txt file to manage your Python dependencies. This blueprint provides a basic structure for your Flask app. You can expand upon this by adding more routes, templates, and static files as needed for your application’s functionality. Good luck with your project! 🚀📈 Deploying a Flask app to a server involves several steps. Here’s a high-level overview of the process:
- Prepare Your App for Deployment: o Ensure your app is production-ready by removing any development environment settings. o Use a production WSGI server like Gunicorn or uWSGI instead of the built-in Flask server.
- Create a Distribution File: o Generate a wheel distribution file of your app using setuptools. o Install the wheel library if not already installed: pip install wheel. o Run python setup.py bdist_wheel to create the distribution file.
- Choose a Hosting Service: o Decide on a hosting service that supports Python applications, such as Heroku, AWS, or a VPS.
- Set Up the Server: o Install the necessary software on the server (e.g., Nginx, Apache). o Configure a reverse proxy to pass requests to your Flask app.
- Secure Your App: o Set up SSL/TLS for HTTPS. o Configure firewalls and security groups as needed.
- Deploy Your App: o Transfer the distribution file to your server. o Set up a virtual environment on the server and install your app using pip. o Configure environment variables, including the SECRET_KEY.
- Run Your App: o Start your Flask app using the production WSGI server. o Ensure it’s running on the correct port and is accessible.
- Monitor and Maintain: o Set up monitoring tools to keep track of your app’s performance and uptime. o Regularly update your app and server software to patch security vulnerabilities. For detailed instructions, you can refer to the Flask documentation on deploying to production1, or follow a tutorial specific to your chosen hosting service2. Remember to test your deployment thoroughly to ensure everything works as expected. Good luck with your Flask app deployment! 🚀📈