├── .DS_Store ├── .gitignore ├── LICENSE ├── README.md ├── data ├── images │ ├── quantpy_twitter_bot.png │ ├── quantpy_twitter_console.png │ ├── raspberrypi_bot.jpg │ ├── twitter_bot_logs.png │ ├── twitter_jupyter_notebook.png │ └── twitter_prompt_engineering.png ├── processed │ └── quants_tweets.txt └── raw │ ├── content-ideas-2.txt │ └── content-ideas.txt ├── main.py ├── notebooks ├── prompt_engineering.ipynb ├── quants_tweets.txt └── quants_tweets_2.txt ├── quantpy_feed ├── __init__.py ├── call_openai.py ├── process_tweets.py ├── twitter.py └── twitter_feed_bot.py └── requirements.txt /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 QuantPy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # quantpy-twitter-bot 2 | 3 | This project automates the Twitter Feed of [QuantPy](https://twitter.com/TheQuantPy) using the OpenAI and Twitter API's. 4 | 5 | 6 | 7 | 8 | ## :pushpin: Current Features 9 | 10 | - utilises OpenAI Chat GPT to generate twitter (X) posts from a list of quantitative python ideas with a specific template file 11 | - develop OpenAI prompt template using Jupyter Notebooks environment for testing response 12 | - tweets are posted to twitter (using tweepy) every 12 hours with the apscheduler module in python 13 | - scripts are run using the operating system service and therefore from the command line of our remote server we can: check the status, stop or start the twitter bot service 14 | - we also have access to the logs generated from the twitter bot 15 | 16 | ## :mountain: Task List 17 | 18 | - [x] Project 1: QuantPy Main Twitter Feed Automation 19 | - [x] Generate Quantitative Finance Twitter Content using OpenAI ChatGPT 20 | - [x] Schedule & Send Tweets using Raspberry Pi Headless Server 21 | - [ ] Project 2: Automate scraping & publishing of top quality news on Quantitative Finance Topics 22 | - [ ] Project 3: Train & Publish specific Quantitative Finance ChatGPT Model 23 | - [ ] Project 4: Allow users to interact with trained model by tagging @TheQuantPy twitter handle on quant finance twitter posts :tada: :champagne: 24 | 25 | ## :hammer_and_wrench: Deployment Steps 26 | 27 | These steps are to be followed to create a clone of the twitter bot and run it on a remote server or rapsberry pi (as I have done here). 28 | 29 | ### :gear: Pre-Steps: 30 | 31 | 1. Create [OpenAI Account for API](https://platform.openai.com/apps) 32 | 2. Create API key for [ChatGPT API](https://platform.openai.com/account/api-keys) 33 | 3. Create Twitter Account for your bot 34 | 4. Create [Developer Account](https://developer.twitter.com/en/portal/dashboard), this can be done for free, however there is a 250 word explanation of use case required. 35 | 5. Add environment variables to a .env file, and have this where you host your app. List of environment variables required and naming convention below: 36 | - OPENAI_API_KEY 37 | - TWITTER_API_KEY 38 | - TWITTER_API_SECRET 39 | - TWITTER_ACCESS_TOKEN 40 | - TWITTER_ACCESS_TOKEN_SECRET 41 | - TWITTER_BEARER_TOKEN 42 | 43 | ### Step 0 (Raspberry Pi): Setup Raspberry Pi 44 | 45 | [Setup Raspberry Pi in Headless mode](https://www.hackster.io/435738/how-to-setup-your-raspberry-pi-headless-8a905f), so you can access it like a remote server. 46 | 47 | ### Step 1: Python3.11+ and Git 48 | 49 | Ensure python 3.11 is installed, and download git. 50 | 51 | ``` 52 | sudo apt update 53 | sudo apt install git 54 | ``` 55 | 56 | ### Step 2: download github repo to remote server 57 | 58 | ``` 59 | git clone https://github.com/TheQuantPy/quantpy-twitter-bot.git 60 | ``` 61 | 62 | ### Step 3: create & activate virtual env 63 | 64 | ### 3a. Enter the github project main folder 65 | 66 | ``` 67 | cd quantpy-twitter-bot 68 | ``` 69 | 70 | ### 3b. create and activate virtual env 71 | 72 | ``` 73 | python -m venv env 74 | source env/bin/activate 75 | ``` 76 | 77 | ### 3c. download requirements 78 | 79 | ``` 80 | pip install -r requirements.txt 81 | ``` 82 | 83 | ### Step 4: setup twitter bot service using `systemctl` 84 | 85 | > [!NOTE] 86 | > Important that twitter_bot.service file is [installed properly](https://gist.github.com/emxsys/a507f3cad928e66f6410e7ac28e2990f) on host server 87 | 88 | We will run out twitter bot script as a service in the operating system so it can hva the following functionality: 89 | 90 | - start, 91 | - stop, 92 | - restart, and 93 | - status. 94 | 95 | We will setup our bot script as a service using [linux operating system sysemd](https://wiki.archlinux.org/title/systemd), which can be commanded using systemctl. 96 | 97 | #### 4a. Setting up the service to run our script in daemon mode on the server: 98 | 99 | ``` 100 | cd /lib/systemd/system/ 101 | sudo nano twitter_bot.service 102 | ``` 103 | 104 | #### 4b. Add the Following Text and save the service file: 105 | 106 | ``` 107 | [Unit] 108 | Description=QuantPy Twitter Bot Service 109 | After=multi-user.target 110 | 111 | [Service] 112 | Type=simple 113 | ExecStart=/home/quantpy/quantpy-twitter-bot/env/bin/python /home/quantpy/quantpy-twitter-bot/main.py 114 | Restart=on-abort 115 | 116 | [Install] 117 | WantedBy=multi-user.target 118 | ``` 119 | 120 | #### 4c. Now that we have our service we need to activate it: 121 | 122 | ``` 123 | sudo chmod 644 /lib/systemd/system/twitter_bot.service 124 | chmod +x /home/quantpy/quantpy-twitter-bot/main.py 125 | sudo systemctl daemon-reload 126 | sudo systemctl enable twitter_bot.service 127 | 128 | ``` 129 | 130 | #### 4d. Now we can access the following commands 131 | 132 | To start service: 133 | 134 | ``` 135 | sudo systemctl start twitter_bot.service 136 | ``` 137 | 138 | To check status: 139 | 140 | ``` 141 | sudo systemctl status twitter_bot.service 142 | ``` 143 | 144 | To stop service: 145 | 146 | ``` 147 | sudo systemctl stop twitter_bot.service 148 | ``` 149 | 150 | To check service logs: 151 | 152 | ``` 153 | sudo journalctl -f -u twitter_bot.service 154 | ``` 155 | 156 | ## The MIT License (MIT) 157 | 158 | Copyright © 2023 QuantPy Pty Ltd 159 | 160 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 161 | 162 | - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 163 | -------------------------------------------------------------------------------- /data/images/quantpy_twitter_bot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/data/images/quantpy_twitter_bot.png -------------------------------------------------------------------------------- /data/images/quantpy_twitter_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/data/images/quantpy_twitter_console.png -------------------------------------------------------------------------------- /data/images/raspberrypi_bot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/data/images/raspberrypi_bot.jpg -------------------------------------------------------------------------------- /data/images/twitter_bot_logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/data/images/twitter_bot_logs.png -------------------------------------------------------------------------------- /data/images/twitter_jupyter_notebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/data/images/twitter_jupyter_notebook.png -------------------------------------------------------------------------------- /data/images/twitter_prompt_engineering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/data/images/twitter_prompt_engineering.png -------------------------------------------------------------------------------- /data/raw/content-ideas-2.txt: -------------------------------------------------------------------------------- 1 | | Number | Topic | Title | 2 | |--------|----------------------------------------|---------------------------------------------------------| 3 | | 1 | Time Value of Money | Understanding the Time Value of Money in Quant Finance | 4 | | 2 | Risk and Return | Quantifying Risk and Return | 5 | | 3 | Modern Portfolio Theory | Mastering Modern Portfolio Theory | 6 | | 4 | Black-Scholes Model | Black-Scholes Model: The ABCs of Option Pricing | 7 | | 5 | Multifactor Models | Exploring Multifactor Models in Finance | 8 | | 6 | Copula Models | Copula Models: The Backbone of Financial Engineering | 9 | | 7 | Stochastic Calculus | Stochastic Calculus for Finance: A Primer | 10 | | 8 | Ito’s Lemma | Ito's Lemma Explained | 11 | | 9 | Quantitative Risk Management | Techniques in Quantitative Risk Management | 12 | | 10 | Simple Moving Average | Building a Simple Moving Average Trading Strategy | 13 | | 11 | Backtesting | Introduction to Backtesting and its Pitfalls | 14 | | 12 | Transaction Costs | Incorporating Transaction Costs in Trading Models | 15 | | 13 | Slippage | Understanding and Accounting for Slippage | 16 | | 14 | Portfolio Optimization | Portfolio Optimization Techniques | 17 | | 15 | QuantLib | Introduction to QuantLib | 18 | | 16 | Zipline | Getting Started with Zipline | 19 | | 17 | Backtrader | Algorithmic Trading with Backtrader | 20 | | 18 | Monte Carlo Simulations | Implementing Monte Carlo Simulations using Python | 21 | | 19 | Time Series Analysis | Time Series Analysis with Statsmodels | 22 | | 20 | Machine Learning | Machine Learning in Quantitative Finance | 23 | | 21 | Cryptocurrency | Cryptocurrency Trading Strategies for Quants | 24 | | 22 | High-Frequency Trading | High-Frequency Trading Strategies | 25 | | 23 | Market Anomalies | Analyzing Famous Market Anomalies | 26 | | 24 | Financial Crises | Breaking Down Financial Crises: A Quant Perspective | 27 | | 25 | Hedge Funds | Exploring Hedge Fund Strategies: Renaissance Technologies| 28 | | 26 | Algorithmic Trading Basics | Algorithmic Trading: A Comprehensive Guide | 29 | | 27 | Behavioral Finance | Behavioral Finance and Quant Strategies | 30 | | 28 | Volatility Modeling | Understanding Volatility: Models and Implications | 31 | | 29 | Bayesian Methods | Bayesian Methods in Finance | 32 | | 30 | Neural Networks | Neural Networks in Finance: A Quick Start Guide | 33 | | 31 | Option Greeks | Understanding Option Greeks: Delta, Gamma, Vega | 34 | | 32 | Value at Risk | Calculating Value at Risk: Methods and Models | 35 | | 33 | Real Options | Real Options in Corporate Finance | 36 | | 34 | Natural Language Processing | NLP in Quant Finance: Sentiment Analysis | 37 | | 35 | Event-Driven Strategies | Event-Driven Trading Strategies | 38 | | 36 | Utility Theory | Utility Theory in Portfolio Management | 39 | | 37 | Mean Reversion | Mean Reversion Strategies: Theory and Practice | 40 | | 38 | GARCH Models | Introduction to GARCH Models | 41 | | 39 | CAPM | Capital Asset Pricing Model: A Quant's View | 42 | | 40 | Cointegration | Understanding Cointegration: A Quant Approach | 43 | | 41 | ARIMA Models | ARIMA Models in Time Series Forecasting | 44 | | 42 | Pairs Trading | Mastering Pairs Trading: Strategies and Techniques | 45 | | 43 | Simulation Methods | Simulation Methods in Quant Finance | 46 | | 44 | CVA and Counterparty Risk | CVA and Counterparty Risk: A Quantitative Analysis | 47 | | 45 | Dynamic Hedging | Dynamic Hedging: Techniques and Strategies | 48 | | 46 | Quantitative Value | Quantitative Value: A Practitioner’s Guide | 49 | | 47 | Option Strategies | Popular Option Strategies: A Quantitative Review | 50 | | 48 | Term Structure of Interest Rates | Understanding the Term Structure of Interest Rates | 51 | | 49 | Markov Chains | Markov Chains in Quantitative Finance | 52 | | 50 | Fixed Income Securities | Quantitative Approaches to Fixed Income Securities | 53 | | 51 | Credit Risk | Quantitative Methods for Credit Risk Analysis | 54 | | 52 | Value Investing | A Quantitative Approach to Value Investing | 55 | | 53 | Reinforcement Learning | Using Reinforcement Learning in Trading Strategies | 56 | | 54 | Econometrics | Introduction to Econometric Models for Quants | 57 | | 55 | Sentiment Analysis | Quantifying Market Sentiment: A Guide | 58 | | 56 | Technical Indicators | How to Use RSI and MACD in Algorithmic Trading | 59 | | 57 | Market Microstructure | Understanding Market Microstructure | 60 | | 58 | Bid-Ask Spread | The Quantitative Analysis of Bid-Ask Spreads | 61 | | 59 | Liquidity | Quantifying Liquidity: Methods and Measures | 62 | | 60 | Fuzzy Logic | Using Fuzzy Logic in Quantitative Finance | 63 | | 61 | Fractional Brownian Motion | Fractional Brownian Motion in Finance: An Introduction | 64 | | 62 | Long-Short Strategies | Long-Short Strategies: A Quant Approach | 65 | | 63 | Convex Optimization | Convex Optimization in Quant Finance | 66 | | 64 | ARDL Models | AutoRegressive Distributed Lag (ARDL) Models in Finance | 67 | | 65 | ETF Arbitrage | Understanding ETF Arbitrage: A Quantitative Guide | 68 | | 66 | Bootstrap Methods | Bootstrap Methods in Finance | 69 | | 67 | Quantitative Strategy Evaluation | Evaluating Quant Strategies: Key Metrics | 70 | | 68 | Kelly Criterion | Using the Kelly Criterion in Trading | 71 | | 69 | Dark Pools | Dark Pools: A Quantitative Perspective | 72 | | 70 | Hedge Fund Replication | Hedge Fund Replication: Quantitative Methods | 73 | | 71 | Data Snooping | Data Snooping: A Quant’s Guide to Avoiding Bias | 74 | | 72 | Non-linear Models | Non-linear Models in Quantitative Finance | 75 | | 73 | Heteroskedasticity | Dealing with Heteroskedasticity in Financial Data | 76 | | 74 | Statistical Arbitrage | Understanding Statistical Arbitrage | 77 | | 75 | Decision Trees | Applying Decision Trees in Finance | 78 | | 76 | Futures and Forwards | Quantitative Analysis of Futures and Forwards | 79 | | 77 | Leverage | Understanding Leverage: A Quantitative Analysis | 80 | | 78 | Fundamentals of ETFs | The Fundamentals of ETFs: A Quant’s Perspective | 81 | | 79 | Trading Psychology | Trading Psychology and Quant Strategies | 82 | | 80 | Copula-based Dependency | Understanding Copula-based Dependency in Finance | 83 | | 81 | Jump-diffusion Models | Jump-diffusion Models in Option Pricing | 84 | | 82 | K-means Clustering | K-means Clustering in Portfolio Management | 85 | | 83 | Spline Methods | Spline Methods for Curve Fitting in Finance | 86 | | 84 | Quants in Investment Banking | Roles of Quants in Investment Banking | 87 | | 85 | Interest Rate Swaps | Quantitative Analysis of Interest Rate Swaps | 88 | | 86 | Energy Derivatives | Quantitative Models for Energy Derivatives | 89 | | 87 | Exotic Options | Pricing Exotic Options: A Quantitative Guide | 90 | | 88 | Student-t Distribution | Student-t Distribution in Quant Finance | 91 | | 89 | Forecasting Volatility | Forecasting Volatility: Models and Methods | 92 | | 90 | Career Paths | Career Paths in Quantitative Finance | 93 | | 91 | PCA in Finance | Principal Component Analysis in Finance | 94 | | 92 | ETF Mechanics | ETF Mechanics: Creation and Redemption | 95 | | 93 | Trend Following | Trend Following Strategies: A Quantitative Approach | 96 | | 94 | Quantitative Momentum | Quantitative Momentum: Strategies and Metrics | 97 | | 95 | Socially Responsible Investing | Quantitative Methods in Socially Responsible Investing | 98 | | 96 | Risk Parity | Understanding Risk Parity in Portfolio Management | 99 | | 97 | Commodity Trading | Quantitative Models for Commodity Trading | 100 | | 98 | Autocorrelation | Detecting Autocorrelation in Financial Time Series | 101 | | 99 | Machine Learning Series | Machine Learning in Finance: A Multi-part Series | 102 | | 100 | Python for Quant Finance Series | Python for Quant Finance: A Comprehensive Guide | 103 | -------------------------------------------------------------------------------- /data/raw/content-ideas.txt: -------------------------------------------------------------------------------- 1 | | Number | Topic | Title |\ 2 | |--------|--------------------------------|---------------------------------------------------------------|\ 3 | | 1 | Time Value of Money | "Unveiling the Magic of Compounding: Time Value of Money" |\ 4 | | 2 | Risk and Return | "Playing the Odds: Understanding Risk and Return" |\ 5 | | 3 | Modern Portfolio Theory | "Crafting the Perfect Portfolio: An Intro to MPT" |\ 6 | | 4 | Black-Scholes Model | "The Black-Scholes Legacy: Revolutionizing Option Pricing" |\ 7 | | 5 | Multifactor Models | "Beyond Beta: Exploring Multifactor Models" |\ 8 | | 6 | Copula Models | "Bridging Dependencies: An Insight into Copula Models" |\ 9 | | 7 | Stochastic Calculus | "The Dance of Chance: Delving into Stochastic Calculus" |\ 10 | | 8 | Ito's Lemma | "Ito's Insight: Unpacking Ito's Lemma" |\ 11 | | 9 | Quantitative Risk Management | "Taming Uncertainty: Quantitative Risk Management Essentials" |\ 12 | | 10 | Simple Moving Average Strategy | "Smooth Moves: SMA Trading Strategy Explained" |\ 13 | | 11 | Backtesting | "Rewinding The Market: The Art of Backtesting" |\ 14 | | 12 | Transaction Costs and Slippage | "The Hidden Costs: Navigating Transaction Costs and Slippage" |\ 15 | | 13 | Portfolio Optimization | "Balancing Act: Portfolio Optimization Techniques" |\ 16 | | 14 | QuantLib Introduction | "Toolkit Talk: A Dive into QuantLib" |\ 17 | | 15 | Implementing Monte Carlo Simulations | "Rolling the Dice: Monte Carlo Simulations in Trading" |\ 18 | | 16 | Time Series Analysis | "Decoding Time: An Adventure into Time Series Analysis" |\ 19 | | 17 | Machine Learning in Finance | "The Finance Algorithm: Machine Learning's Role" |\ 20 | | 18 | Cryptocurrency Quant Strategies | "Crypto Conundrums: Quant Strategies in Cryptocurrency Markets" |\ 21 | | 19 | High-frequency Trading Strategies | "Milliseconds to Millions: High-frequency Trading Strategies" |\ 22 | | 20 | Market Anomalies Analysis | "Bizarre Bazaars: Analyzing Market Anomalies" |\ 23 | | 21 | Financial Crises Analysis | "Crash Course: Analyzing Major Financial Crises" |\ 24 | | 22 | Strategies of Quant Hedge Funds | "Quantum Leaps: Strategies of Top Quant Hedge Funds" |\ 25 | | 23 | Zipline Library Introduction | "Zipping Through Data: An Introduction to Zipline Library" |\ 26 | | 24 | Backtrader Library Introduction | "Trade the Code: Getting Started with Backtrader" |\ 27 | | 25 | Statsmodels Library Introduction | "Modeling Market Mysteries with Statsmodels" |\ 28 | | 26 | Interest Rate Models | "Rate of Change: Diving into Interest Rate Models" |\ 29 | | 27 | Credit Risk Models | "Credit Where It's Due: Unveiling Credit Risk Models" |\ 30 | | 28 | Derivative Pricing | "Price Tag on Risk: The World of Derivative Pricing" |\ 31 | | 29 | Option Pricing | "Options Unveiled: The Pricing Paradigm" |\ 32 | | 30 | Volatility Forecasting | "Predicting Pandemonium: Volatility Forecasting Techniques" |\ 33 | | 31 | Arbitrage Pricing Theory | "Free Lunch? Unpacking Arbitrage Pricing Theory" |\ 34 | | 32 | Behavioral Finance | "Mind Over Markets: A Look into Behavioral Finance" |\ 35 | | 33 | Equity Quant Strategies | "Stocks and Quants: Equity Quantitative Strategies" |\ 36 | | 34 | Fixed Income Quant Strategies | "Bonding with Quant: Fixed Income Quantitative Strategies" |\ 37 | | 35 | Commodities Quant Strategies | "Golden Opportunities: Commodities Quantitative Strategies" |\ 38 | | 36 | Forex Quant Strategies | "Currency Code: Forex Quantitative Strategies" |\ 39 | | 37 | Asset Allocation Strategies | "The Allocation Equation: Asset Allocation Strategies" |\ 40 | | 38 | Liquidity Risk Management | "Liquid or Illiquid? Navigating Liquidity Risk" |\ 41 | | 39 | Performance Measurement | "Measuring Mastery: Performance Measurement in Quant Finance" |\ 42 | | 40 | Hedge Fund Structure and Strategies| "Hedge Fund Hierarchy: Structure and Strategies Uncovered" |\ 43 | | 41 | Asset Pricing Models | "Valuing Varieties: A Look at Asset Pricing Models" |\ 44 | | 42 | Market Microstructure | "Market Mosaic: Delving into Market Microstructure" |\ 45 | | 43 | Algorithmic Trading Risks | "Algo Angst: Navigating Risks in Algorithmic Trading" |\ 46 | | 44 | Regulatory Environment | "Rulebook of the Ruled: Understanding Financial Regulation" |\ 47 | | 45 | Portfolio Performance Analysis | "Portfolio's Proof: Delving into Performance Analysis" |\ 48 | | 46 | Value at Risk (VaR) | "VaR's Vantage: Unpacking Value at Risk" |\ 49 | | 47 | Stress Testing | "Financial Fitness: The Essence of Stress Testing" |\ 50 | | 48 | Exotic Options Pricing | "Beyond Vanilla: Pricing Exotic Options" |\ 51 | | 49 | Sentiment Analysis in Finance | "Feel the Market's Pulse: Sentiment Analysis Unveiled" |\ 52 | | 50 | Systematic Trading Strategies | "Systematic Success: Exploring Systematic Trading Strategies" |\ 53 | | 51 | Trading Psychology | "Mind over Markets: Unpacking Trading Psychology" |\ 54 | | 52 | Alternative Data in Finance | "Alt Data Alchemy: The New Gold in Finance" |\ 55 | | 53 | ETF Trading Strategies | "ETF Expeditions: Unveiling Trading Strategies" |\ 56 | | 54 | Quantitative Model Validation | "Model Marvel or Mirage: The Art of Quant Model Validation" |\ 57 | | 55 | Factor Investing | "Factor Feast: Diving into Factor Investing" |\ 58 | | 56 | Futures and Forwards | "Future-Forward Finance: Exploring Futures and Forwards" |\ 59 | | 57 | Swap Contracts | "Switcheroo: Unraveling Swap Contracts" |\ 60 | | 58 | Risk Parity Strategies | "Balancing Act: Delving into Risk Parity Strategies" |\ 61 | | 59 | Technical Analysis | "Charting the Course: Technical Analysis Techniques" |\ 62 | | 60 | Event-Driven Trading Strategies| "Eventful Earnings: Mastering Event-Driven Trading Strategies" |\ 63 | | 61 | Fundamental Analysis | "Beyond Numbers: The Essence of Fundamental Analysis" |\ 64 | | 62 | Statistical Arbitrage | "Statistical Stakes: A Dive into Statistical Arbitrage" |\ 65 | | 63 | Portfolio Construction | "Building Financial Fortresses: Portfolio Construction Essentials" |\ 66 | | 64 | High-Frequency Trading Technology | "Speed Demons: Tech Behind High-Frequency Trading" |\ 67 | | 65 | Momentum Trading Strategies | "Momentum Mysteries: Unveiling Momentum Trading Strategies" |\ 68 | | 66 | Market Making Strategies | "Market Maestro: Mastering Market Making Strategies" |\ 69 | | 67 | Pairs Trading | "Twins of Trade: Pairs Trading Explained" |\ 70 | | 68 | Machine Learning Algorithm Tuning | "Tuning the Financial Tune: ML Algorithm Tuning in Finance" |\ 71 | | 69 | Neural Networks in Finance | "Financial Foresight: Neural Networks in Action" |\ 72 | | 70 | Reinforcement Learning in Trading | "Rewarding Routines: Reinforcement Learning in Trading" |\ 73 | | 71 | Blockchain Technology | "Block by Block: Unpacking Blockchain Technology" |\ 74 | | 72 | Smart Contracts | "Contractual Clarity: Delving into Smart Contracts" |\ 75 | | 73 | Quantitative Easing Impact | "Easing into Economics: Impact of Quantitative Easing" |\ 76 | | 74 | Inflation Hedging Strategies | "Inflation Insulation: Hedging Strategies Explored" |\ 77 | | 75 | Central Bank Policies | "Banking on Policy: Unpacking Central Bank Moves" |\ 78 | | 76 | Financial Data Cleaning and Processing | "Data Detox: Cleaning and Processing Financial Data" |\ 79 | | 77 | Quantitative Finance Career Paths | "Quant Quest: Exploring Career Paths in Quantitative Finance" |\ 80 | | 78 | Real-world Quantitative Finance Projects| "From Theory to Thriving: Real-world Quant Projects" |\ 81 | | 79 | Financial Ethics and Compliance | "Ethical Earnings: Finance Ethics and Compliance" |\ 82 | | 80 | Trading Platform Development | "Platform Power-play: Developing Your Trading Platform" |\ 83 | | 81 | Python Libraries for Finance | "Library Lore: Python Libraries Every Quant Should Know" |\ 84 | | 82 | Order Book Dynamics | "Booked on Books: Understanding Order Book Dynamics" |\ 85 | | 83 | Derivatives Hedging Strategies | "Derivative Defenses: Mastering Hedging Strategies" |\ 86 | | 84 | Quantitative Finance Interviews Prep| "Quant Quizzing: Acing Quantitative Finance Interviews" |\ 87 | | 85 | Financial Networks Analysis | "Network of Net-worth: Unveiling Financial Networks" |\ 88 | | 86 | Market Impact Models | "Impactful Insights: Delving into Market Impact Models" |\ 89 | | 87 | Trading Signal Generation | "Signal Success: Generating and Evaluating Trading Signals" |\ 90 | | 88 | Latency in Trading Systems | "Latent Lessons: The Role of Latency in Trading Systems" |\ 91 | | 89 | Market Anomalies Exploitation | "Anomalous Achievements: Exploiting Market Anomalies" |\ 92 | | 90 | Trading System Evaluation | "Systematic Scrutiny: Evaluating Trading Systems" |\ 93 | | 91 | Credit Derivatives | "Credit Chronicles: An Overview of Credit Derivatives" |\ 94 | | 92 | Sentiment-Driven Trading Strategies | "Sentimental Journeys: Trading on Market Mood" |\ 95 | | 93 | Survival Analysis in Finance | "Survival of the Fittest: Applying Survival Analysis" |\ 96 | | 94 | Seasonality Effects in Markets | "Seasonal Strategies: Navigating Market Seasonality" |\ 97 | | 95 | Liquidity Provision Strategies | "Liquid Logic: Mastering Liquidity Provision Strategies" |\ 98 | | 96 | Game Theory in Finance | "Financial Foresight: Game Theory in Action" |\ 99 | | 97 | Real Estate Quantitative Analysis | "Realty Reality: Quantitative Analysis in Real Estate" |\ 100 | | 98 | Trading Infrastructure Development | "Infrastucture Insights: Building Robust Trading Systems" |\ 101 | | 99 | Financial Data Visualization | "Visual Wealth: Financial Data Visualization Techniques" |\ 102 | | 100 | High-Frequency Trading | "The Need for Speed: Inside High-Frequency Trading" |\ -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import time 2 | import logging 3 | from quantpy_feed.twitter_feed_bot import run_quantpy_feed_bot 4 | from apscheduler.schedulers.background import BackgroundScheduler 5 | 6 | # set up logging to file 7 | logging.basicConfig( 8 | level=logging.INFO, 9 | format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s", 10 | datefmt="%y-%m-%d %H:%M", 11 | filename="twitter-bot.log", 12 | filemode="a", 13 | ) 14 | 15 | if __name__ == "__main__": 16 | # Creates a default Background Scheduler 17 | sched = BackgroundScheduler(daemon=True) 18 | 19 | # run once to publish 20 | run_quantpy_feed_bot() 21 | 22 | # then add to scheduler 23 | sched.add_job(run_quantpy_feed_bot, "interval", hours=12) 24 | 25 | # start scheduler 26 | sched.start() 27 | 28 | while True: 29 | time.sleep(60) 30 | -------------------------------------------------------------------------------- /notebooks/prompt_engineering.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "1d37d6de-cbd0-4fe4-98f1-a8c41113bb84", 6 | "metadata": {}, 7 | "source": [ 8 | "# QuantPy Twitter Bot\n", 9 | "\n", 10 | "This is a jupyter notebook, to guid through the process of prompt engineering and storing the data within python dataclasses.\n", 11 | "\n", 12 | "## Prompt Engineering\n", 13 | "\n", 14 | "Langchain prompting template adapted from [https://github.com/gkamradt](https://github.com/gkamradt/langchain-tutorials/blob/36957e9be70c09dcadaefb2caf790111170dd132/bots/Twitter_Reply_Bot/Twitter%20Reply%20Bot%20Notebook.ipynb)\n", 15 | "\n", 16 | "More on prompt engineering and langchain can be found [here](https://python.langchain.com/docs/modules/model_io/prompts/prompt_templates/prompts_pipelining)\n", 17 | "\n", 18 | "Note on \"database\" structure: \n", 19 | " - although not perfect, our database for the moment will be regular text files separated by '|' (divisors) with each row being a new entry." 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 4, 25 | "id": "896cab48-886e-4724-864d-6600e5d99cff", 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "import os\n", 30 | "import re\n", 31 | "from dotenv import load_dotenv\n", 32 | "\n", 33 | "from langchain.chat_models import ChatOpenAI\n", 34 | "from langchain.prompts import (\n", 35 | " ChatPromptTemplate,\n", 36 | " SystemMessagePromptTemplate,\n", 37 | " AIMessagePromptTemplate,\n", 38 | " HumanMessagePromptTemplate,\n", 39 | ")" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "id": "c4e5a906-814e-45dd-85b6-db457bd82414", 45 | "metadata": {}, 46 | "source": [ 47 | "## Setting up variables" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 5, 53 | "id": "dbdd56e0", 54 | "metadata": {}, 55 | "outputs": [ 56 | { 57 | "name": "stdout", 58 | "output_type": "stream", 59 | "text": [ 60 | "Application Dir: \n", 61 | "\t/Users/jonathonemerick/Documents/dev/quantpy-twitter-bot\n", 62 | "Raw Tweet File Dir: \n", 63 | "\t/Users/jonathonemerick/Documents/dev/quantpy-twitter-bot/data/raw/content-ideas.txt\n", 64 | "Processed Tweet File Dir: \n", 65 | "\t/Users/jonathonemerick/Documents/dev/quantpy-twitter-bot/data/processed/quants_tweets.txt\n" 66 | ] 67 | } 68 | ], 69 | "source": [ 70 | "load_dotenv()\n", 71 | "\n", 72 | "# Secret keys from .env file\n", 73 | "OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n", 74 | "\n", 75 | "# Directory Variables\n", 76 | "CUR_DIR = os.path.dirname(os.path.abspath('__file__'))\n", 77 | "APP_DIR = os.path.abspath(os.path.join(CUR_DIR, os.pardir))\n", 78 | "LOG_FILE = os.path.join(APP_DIR, \"twitter-bot.log\")\n", 79 | "RAW_TEXT_FILE = os.path.join(APP_DIR, \"data/raw/content-ideas.txt\")\n", 80 | "TEXT_FILE = os.path.join(APP_DIR, \"data/processed/quants_tweets.txt\")\n", 81 | "\n", 82 | "# print variables\n", 83 | "print(f\"Application Dir: \\n\\t{APP_DIR}\")\n", 84 | "print(f\"Raw Tweet File Dir: \\n\\t{RAW_TEXT_FILE}\")\n", 85 | "print(f\"Processed Tweet File Dir: \\n\\t{TEXT_FILE}\")" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "id": "0406fc4f-5c00-42e9-959a-71336cc0ce9d", 91 | "metadata": {}, 92 | "source": [ 93 | "## Prompt Engineering with ChatGPT" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 4, 99 | "id": "91098cf3-ed6c-4ab0-8e69-e7e300622c4a", 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "llm = ChatOpenAI(temperature=0.3,\n", 104 | " openai_api_key=OPENAI_API_KEY,\n", 105 | " model_name='gpt-3.5-turbo-0613',\n", 106 | " )" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 5, 112 | "id": "0011dbdb-1c38-4416-bec8-f57a5e017e9b", 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "def generate_response(\n", 117 | " llm: ChatOpenAI, quant_topic: str, quant_title: str\n", 118 | ") -> tuple[str, str]:\n", 119 | " \"\"\"Generate AI Twitter Content for QuantPy Twitter Account\n", 120 | "\n", 121 | " Parameters:\n", 122 | " - llm: pre-trained ChatOpenAi large language model\n", 123 | " - quant_topic: Topic in Quant Finance\n", 124 | " - quant_topic: Topic in Quant Finance\n", 125 | "\n", 126 | " Returns:\n", 127 | " - tuple[long response,short reposonse]: Chat GPT long and short responses\n", 128 | " \"\"\"\n", 129 | " # System Template for LLM to follow\n", 130 | " system_template = \"\"\"\n", 131 | " You are an incredibly wise and smart quantitative analyst that lives and breathes the world of quantitative finance.\n", 132 | " Your goal is to writing short-form content for twitter given a `topic` in the area of quantitative finance and a `title` from the user.\n", 133 | " \n", 134 | " % RESPONSE TONE:\n", 135 | "\n", 136 | " - Your response should be given in an active voice and be opinionated\n", 137 | " - Your tone should be serious w/ a hint of wit and sarcasm\n", 138 | " \n", 139 | " % RESPONSE FORMAT:\n", 140 | " \n", 141 | " - Be extremely clear and concise\n", 142 | " - Respond with phrases no longer than two sentences\n", 143 | " - Do not respond with emojis\n", 144 | " \n", 145 | " % RESPONSE CONTENT:\n", 146 | "\n", 147 | " - Include specific examples of where this is used in the quantitative finance space\n", 148 | " - If you don't have an answer, say, \"Sorry, I'll have to ask the Quant Finance Gods!\" \n", 149 | "\n", 150 | " % RESPONSE TEMPLATE:\n", 151 | "\n", 152 | " - Here is the response structure: \n", 153 | " Hook: Captivate with a one-liner.\n", 154 | " Intro: Briefly introduce the topic.\n", 155 | " Explanation: Simplify the core idea.\n", 156 | " Application: Note real-world relevance.\n", 157 | " Closing: Reflective one-liner.\n", 158 | " Action: Short engagement call.\n", 159 | " Engagement: Quick question.\n", 160 | " \n", 161 | " \"\"\"\n", 162 | " # system prompt template to follow\n", 163 | " system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)\n", 164 | "\n", 165 | " # human template for input\n", 166 | " human_template = \"topic to write about is {topic}, and the title will be {title}. Keep the total response under 200 words total!\"\n", 167 | " human_message_prompt = HumanMessagePromptTemplate.from_template(\n", 168 | " human_template, input_variables=[\"topic\", \"title\"]\n", 169 | " )\n", 170 | "\n", 171 | " # chat prompt template construction\n", 172 | " chat_prompt = ChatPromptTemplate.from_messages(\n", 173 | " [system_message_prompt, human_message_prompt]\n", 174 | " )\n", 175 | "\n", 176 | " # get a completed chat using formatted template with topic and title\n", 177 | " final_prompt = chat_prompt.format_prompt(\n", 178 | " topic=quant_topic, title=quant_title\n", 179 | " ).to_messages()\n", 180 | "\n", 181 | " # pass template through llm and extract content attribute\n", 182 | " first_response = llm(final_prompt).content\n", 183 | "\n", 184 | " # construct AI template, to pass back OpenAI response\n", 185 | " ai_message_prompt = AIMessagePromptTemplate.from_template(first_response)\n", 186 | "\n", 187 | " # additional prompt to remind ChatGPT of length requirement\n", 188 | " reminder_template = \"This was good, but way too long, please make your response much more concise and much shorter! Make phrases no longer than 15 words in total. Please maintain the existing template.\"\n", 189 | " reminder_prompt = HumanMessagePromptTemplate.from_template(reminder_template)\n", 190 | "\n", 191 | " # chat prompt template construction with additional AI response and length reminder\n", 192 | " chat_prompt2 = ChatPromptTemplate.from_messages(\n", 193 | " [system_message_prompt, human_template, ai_message_prompt, reminder_prompt]\n", 194 | " )\n", 195 | "\n", 196 | " # get a completed chat using formatted template with topic and title\n", 197 | " final_prompt = chat_prompt2.format_prompt(\n", 198 | " topic=quant_topic, title=quant_title\n", 199 | " ).to_messages()\n", 200 | "\n", 201 | " # pass template through llm and extract content attribute\n", 202 | " short_response = llm(final_prompt).content\n", 203 | "\n", 204 | " return first_response, short_response" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "id": "ad1062bd-29b0-48e9-9ad0-5416018468ce", 210 | "metadata": {}, 211 | "source": [ 212 | "## Run generate response" 213 | ] 214 | }, 215 | { 216 | "cell_type": "code", 217 | "execution_count": 6, 218 | "id": "db0bbe9b-2446-48ab-a0f6-b5a3f7632886", 219 | "metadata": {}, 220 | "outputs": [], 221 | "source": [ 222 | "first_response, short_response = generate_response(\n", 223 | " llm, \n", 224 | " quant_topic='Time Value of Money', \n", 225 | " quant_title='Unveiling the Magic of Compounding: Time Value of Money'\n", 226 | " )" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": 8, 232 | "id": "c7a4fece-8402-43ec-9953-7f2269192ade", 233 | "metadata": {}, 234 | "outputs": [ 235 | { 236 | "data": { 237 | "text/plain": [ 238 | "\"Hook: Unveiling the Magic of Compounding: Time Value of Money - Money today is worth more than tomorrow!\\n\\nIntro: The Time Value of Money: money available now is worth more due to potential growth.\\n\\nExplanation: It's the backbone of finance, considering opportunity cost and growth potential.\\n\\nApplication: Used in present/future value calculations, bond pricing, options valuation, and investment evaluation.\\n\\nClosing: Don't underestimate compounding! It's a financial superpower that can turn savings into fortune.\\n\\nAction: Start harnessing compounding today by investing wisely and letting time work its magic.\\n\\nEngagement: What's your favorite example of the Time Value of Money in action? #CompoundingMagic\"" 239 | ] 240 | }, 241 | "execution_count": 8, 242 | "metadata": {}, 243 | "output_type": "execute_result" 244 | } 245 | ], 246 | "source": [ 247 | "short_response" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": 9, 253 | "id": "29cc4abd-8773-4ab9-8dee-7829c936ea91", 254 | "metadata": {}, 255 | "outputs": [], 256 | "source": [ 257 | "# helper lambda functions to quickly cound dict values\n", 258 | "count_length = lambda d: sum(len(d[val]) for val in d)\n", 259 | "count_words = lambda d: sum(len(re.findall(r'\\w+', d[val])) for val in d)\n", 260 | "\n", 261 | "# Extract OpenAI response from given list of key words from template in system prompt Template\n", 262 | "key_list=[\"Hook\", \"Intro\", \"Explanation\", \"Application\", \"Closing\", \"Action\", \"Engagement\"]\n", 263 | "def extract_tweet(openai_tweet: str, key_list: list) -> dict:\n", 264 | " \"\"\"Creates dictionary from Openai response using keyword template\n", 265 | "\n", 266 | " Parameters:\n", 267 | " - openai_tweet: \n", 268 | " - key_list: list key words used for searching reponse template\n", 269 | "\n", 270 | " Returns:\n", 271 | " - dictionary: templated tweet\n", 272 | " \"\"\"\n", 273 | " template = {}\n", 274 | " # Iterate through key list\n", 275 | " for i, key in enumerate(key_list):\n", 276 | " # find starting position\n", 277 | " start = openai_tweet.find(key_list[i])+len(key_list[i])+2\n", 278 | " if i != len(key_list) - 1:\n", 279 | " # using ending position, subset str and append to template\n", 280 | " end = openai_tweet.find(key_list[i+1])\n", 281 | " line = openai_tweet[start:end]\n", 282 | " template[key_list[i]] = line\n", 283 | " else:\n", 284 | " # if final word in list, only subsection by start word\n", 285 | " template[key_list[i]] = openai_tweet[start:]\n", 286 | " return template" 287 | ] 288 | }, 289 | { 290 | "cell_type": "markdown", 291 | "id": "61453d0d-6f7b-4044-9a58-d14b6436fca9", 292 | "metadata": {}, 293 | "source": [ 294 | "## Long Response" 295 | ] 296 | }, 297 | { 298 | "cell_type": "code", 299 | "execution_count": 10, 300 | "id": "aea93379-daaf-4da4-9a58-d34b6fbcdd18", 301 | "metadata": {}, 302 | "outputs": [ 303 | { 304 | "data": { 305 | "text/plain": [ 306 | "{'Hook': 'Unveiling the Magic of Compounding: Time Value of Money - Discover the power of compounding and how it can make your money work harder than a caffeinated quant!\\n\\n',\n", 307 | " 'Intro': 'The Time Value of Money is the financial concept that money available today is worth more than the same amount in the future due to its potential to earn interest or investment returns.\\n\\n',\n", 308 | " 'Explanation': 'Time Value of Money is the backbone of finance, reminding us that a dollar today is worth more than a dollar tomorrow. It takes into account the opportunity cost of money and the potential for growth over time.\\n\\n',\n", 309 | " 'Application': 'This concept is used extensively in various areas of quantitative finance, such as calculating present value and future value of cash flows, determining bond prices, valuing options and derivatives, and even evaluating investment opportunities.\\n\\n',\n", 310 | " 'Closing': \"So, don't underestimate the power of compounding! It's like a financial superpower that can turn your savings into a fortune over time.\\n\\n\",\n", 311 | " 'Action': 'Start harnessing the power of compounding today by investing wisely and letting time work its magic.\\n\\n',\n", 312 | " 'Engagement': \"What's your favorite example of the Time Value of Money in action? #CompoundingMagic\"}" 313 | ] 314 | }, 315 | "execution_count": 10, 316 | "metadata": {}, 317 | "output_type": "execute_result" 318 | } 319 | ], 320 | "source": [ 321 | "extract_tweet(first_response, key_list)" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "id": "5c395b77-1cbe-4d50-a5c9-b4142447e850", 327 | "metadata": {}, 328 | "source": [ 329 | "## Short Response" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": 11, 335 | "id": "2bc4f946-ed5d-4ff0-bc71-0e7693af4aed", 336 | "metadata": {}, 337 | "outputs": [ 338 | { 339 | "data": { 340 | "text/plain": [ 341 | "{'Hook': 'Unveiling the Magic of Compounding: Time Value of Money - Money today is worth more than tomorrow!\\n\\n',\n", 342 | " 'Intro': 'The Time Value of Money: money available now is worth more due to potential growth.\\n\\n',\n", 343 | " 'Explanation': \"It's the backbone of finance, considering opportunity cost and growth potential.\\n\\n\",\n", 344 | " 'Application': 'Used in present/future value calculations, bond pricing, options valuation, and investment evaluation.\\n\\n',\n", 345 | " 'Closing': \"Don't underestimate compounding! It's a financial superpower that can turn savings into fortune.\\n\\n\",\n", 346 | " 'Action': 'Start harnessing compounding today by investing wisely and letting time work its magic.\\n\\n',\n", 347 | " 'Engagement': \"What's your favorite example of the Time Value of Money in action? #CompoundingMagic\"}" 348 | ] 349 | }, 350 | "execution_count": 11, 351 | "metadata": {}, 352 | "output_type": "execute_result" 353 | } 354 | ], 355 | "source": [ 356 | "extract_tweet(short_response, key_list)" 357 | ] 358 | }, 359 | { 360 | "cell_type": "markdown", 361 | "id": "f21a3b45-0648-47bf-bf1d-005dd98c4848", 362 | "metadata": {}, 363 | "source": [ 364 | "## Preprocessing content-ideas from text file\n", 365 | "\n", 366 | "Take text file in table structure from GPT and process it by line divisors (|).\n", 367 | "Then create dicitonary and store in desired format back to text file.\n", 368 | "\n", 369 | "An example of the table structure is below.\n", 370 | "\n", 371 | "| Number | Topic | Title |\n", 372 | "| --- | --- | --- |\n", 373 | "| 1 | Time Value of Money | \"Unveiling the Magic of Compounding: Time Value of Money\" |\n", 374 | "| 2 | Risk and Return | \"Playing the Odds: Understanding Risk and Return\" |\n", 375 | "| 3 | Modern Portfolio Theory | \"Crafting the Perfect Portfolio: An Intro to MPT\" |\n" 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": 12, 381 | "id": "22fa0e02-9408-48b2-8900-3742efa28b1c", 382 | "metadata": {}, 383 | "outputs": [ 384 | { 385 | "name": "stdout", 386 | "output_type": "stream", 387 | "text": [ 388 | "1_Time Value of Money_Unveiling the Magic of Compounding: Time Value of Money\n", 389 | "2_Risk and Return_Playing the Odds: Understanding Risk and Return\n", 390 | "3_Modern Portfolio Theory_Crafting the Perfect Portfolio: An Intro to MPT\n", 391 | "4_Black-Scholes Model_The Black-Scholes Legacy: Revolutionizing Option Pricing\n", 392 | "5_Multifactor Models_Beyond Beta: Exploring Multifactor Models\n", 393 | "6_Copula Models_Bridging Dependencies: An Insight into Copula Models\n", 394 | "7_Stochastic Calculus_The Dance of Chance: Delving into Stochastic Calculus\n", 395 | "8_Ito's Lemma_Ito's Insight: Unpacking Ito's Lemma\n", 396 | "9_Quantitative Risk Management_Taming Uncertainty: Quantitative Risk Management Essentials\n", 397 | "10_Simple Moving Average Strategy_Smooth Moves: SMA Trading Strategy Explained\n", 398 | "11_Backtesting_Rewinding The Market: The Art of Backtesting\n", 399 | "12_Transaction Costs and Slippage_The Hidden Costs: Navigating Transaction Costs and Slippage\n", 400 | "13_Portfolio Optimization_Balancing Act: Portfolio Optimization Techniques\n", 401 | "14_QuantLib Introduction_Toolkit Talk: A Dive into QuantLib\n", 402 | "15_Implementing Monte Carlo Simulations_Rolling the Dice: Monte Carlo Simulations in Trading\n", 403 | "16_Time Series Analysis_Decoding Time: An Adventure into Time Series Analysis\n", 404 | "17_Machine Learning in Finance_The Finance Algorithm: Machine Learning's Role\n", 405 | "18_Cryptocurrency Quant Strategies_Crypto Conundrums: Quant Strategies in Cryptocurrency Markets\n", 406 | "19_High-frequency Trading Strategies_Milliseconds to Millions: High-frequency Trading Strategies\n", 407 | "20_Market Anomalies Analysis_Bizarre Bazaars: Analyzing Market Anomalies\n", 408 | "21_Financial Crises Analysis_Crash Course: Analyzing Major Financial Crises\n", 409 | "22_Strategies of Quant Hedge Funds_Quantum Leaps: Strategies of Top Quant Hedge Funds\n", 410 | "23_Zipline Library Introduction_Zipping Through Data: An Introduction to Zipline Library\n", 411 | "24_Backtrader Library Introduction_Trade the Code: Getting Started with Backtrader\n", 412 | "25_Statsmodels Library Introduction_Modeling Market Mysteries with Statsmodels\n", 413 | "26_Interest Rate Models_Rate of Change: Diving into Interest Rate Models\n", 414 | "27_Credit Risk Models_Credit Where It's Due: Unveiling Credit Risk Models\n", 415 | "28_Derivative Pricing_Price Tag on Risk: The World of Derivative Pricing\n", 416 | "29_Option Pricing_Options Unveiled: The Pricing Paradigm\n", 417 | "30_Volatility Forecasting_Predicting Pandemonium: Volatility Forecasting Techniques\n", 418 | "31_Arbitrage Pricing Theory_Free Lunch? Unpacking Arbitrage Pricing Theory\n", 419 | "32_Behavioral Finance_Mind Over Markets: A Look into Behavioral Finance\n", 420 | "33_Equity Quant Strategies_Stocks and Quants: Equity Quantitative Strategies\n", 421 | "34_Fixed Income Quant Strategies_Bonding with Quant: Fixed Income Quantitative Strategies\n", 422 | "35_Commodities Quant Strategies_Golden Opportunities: Commodities Quantitative Strategies\n", 423 | "36_Forex Quant Strategies_Currency Code: Forex Quantitative Strategies\n", 424 | "37_Asset Allocation Strategies_The Allocation Equation: Asset Allocation Strategies\n", 425 | "38_Liquidity Risk Management_Liquid or Illiquid? Navigating Liquidity Risk\n", 426 | "39_Performance Measurement_Measuring Mastery: Performance Measurement in Quant Finance\n", 427 | "40_Hedge Fund Structure and Strategies_Hedge Fund Hierarchy: Structure and Strategies Uncovered\n", 428 | "41_Asset Pricing Models_Valuing Varieties: A Look at Asset Pricing Models\n", 429 | "42_Market Microstructure_Market Mosaic: Delving into Market Microstructure\n", 430 | "43_Algorithmic Trading Risks_Algo Angst: Navigating Risks in Algorithmic Trading\n", 431 | "44_Regulatory Environment_Rulebook of the Ruled: Understanding Financial Regulation\n", 432 | "45_Portfolio Performance Analysis_Portfolio's Proof: Delving into Performance Analysis\n", 433 | "46_Value at Risk (VaR)_VaR's Vantage: Unpacking Value at Risk\n", 434 | "47_Stress Testing_Financial Fitness: The Essence of Stress Testing\n", 435 | "48_Exotic Options Pricing_Beyond Vanilla: Pricing Exotic Options\n", 436 | "49_Sentiment Analysis in Finance_Feel the Market's Pulse: Sentiment Analysis Unveiled\n", 437 | "50_Systematic Trading Strategies_Systematic Success: Exploring Systematic Trading Strategies\n", 438 | "51_Trading Psychology_Mind over Markets: Unpacking Trading Psychology\n", 439 | "52_Alternative Data in Finance_Alt Data Alchemy: The New Gold in Finance\n", 440 | "53_ETF Trading Strategies_ETF Expeditions: Unveiling Trading Strategies\n", 441 | "54_Quantitative Model Validation_Model Marvel or Mirage: The Art of Quant Model Validation\n", 442 | "55_Factor Investing_Factor Feast: Diving into Factor Investing\n", 443 | "56_Futures and Forwards_Future-Forward Finance: Exploring Futures and Forwards\n", 444 | "57_Swap Contracts_Switcheroo: Unraveling Swap Contracts\n", 445 | "58_Risk Parity Strategies_Balancing Act: Delving into Risk Parity Strategies\n", 446 | "59_Technical Analysis_Charting the Course: Technical Analysis Techniques\n", 447 | "60_Event-Driven Trading Strategies_Eventful Earnings: Mastering Event-Driven Trading Strategies\n", 448 | "61_Fundamental Analysis_Beyond Numbers: The Essence of Fundamental Analysis\n", 449 | "62_Statistical Arbitrage_Statistical Stakes: A Dive into Statistical Arbitrage\n", 450 | "63_Portfolio Construction_Building Financial Fortresses: Portfolio Construction Essentials\n", 451 | "64_High-Frequency Trading Technology_Speed Demons: Tech Behind High-Frequency Trading\n", 452 | "65_Momentum Trading Strategies_Momentum Mysteries: Unveiling Momentum Trading Strategies\n", 453 | "66_Market Making Strategies_Market Maestro: Mastering Market Making Strategies\n", 454 | "67_Pairs Trading_Twins of Trade: Pairs Trading Explained\n", 455 | "68_Machine Learning Algorithm Tuning_Tuning the Financial Tune: ML Algorithm Tuning in Finance\n", 456 | "69_Neural Networks in Finance_Financial Foresight: Neural Networks in Action\n", 457 | "70_Reinforcement Learning in Trading_Rewarding Routines: Reinforcement Learning in Trading\n", 458 | "71_Blockchain Technology_Block by Block: Unpacking Blockchain Technology\n", 459 | "72_Smart Contracts_Contractual Clarity: Delving into Smart Contracts\n", 460 | "73_Quantitative Easing Impact_Easing into Economics: Impact of Quantitative Easing\n", 461 | "74_Inflation Hedging Strategies_Inflation Insulation: Hedging Strategies Explored\n", 462 | "75_Central Bank Policies_Banking on Policy: Unpacking Central Bank Moves\n", 463 | "76_Financial Data Cleaning and Processing_Data Detox: Cleaning and Processing Financial Data\n", 464 | "77_Quantitative Finance Career Paths_Quant Quest: Exploring Career Paths in Quantitative Finance\n", 465 | "78_Real-world Quantitative Finance Projects_From Theory to Thriving: Real-world Quant Projects\n", 466 | "79_Financial Ethics and Compliance_Ethical Earnings: Finance Ethics and Compliance\n", 467 | "80_Trading Platform Development_Platform Power-play: Developing Your Trading Platform\n", 468 | "81_Python Libraries for Finance_Library Lore: Python Libraries Every Quant Should Know\n", 469 | "82_Order Book Dynamics_Booked on Books: Understanding Order Book Dynamics\n", 470 | "83_Derivatives Hedging Strategies_Derivative Defenses: Mastering Hedging Strategies\n", 471 | "84_Quantitative Finance Interviews Prep_Quant Quizzing: Acing Quantitative Finance Interviews\n", 472 | "85_Financial Networks Analysis_Network of Net-worth: Unveiling Financial Networks\n", 473 | "86_Market Impact Models_Impactful Insights: Delving into Market Impact Models\n", 474 | "87_Trading Signal Generation_Signal Success: Generating and Evaluating Trading Signals\n", 475 | "88_Latency in Trading Systems_Latent Lessons: The Role of Latency in Trading Systems\n", 476 | "89_Market Anomalies Exploitation_Anomalous Achievements: Exploiting Market Anomalies\n", 477 | "90_Trading System Evaluation_Systematic Scrutiny: Evaluating Trading Systems\n", 478 | "91_Credit Derivatives_Credit Chronicles: An Overview of Credit Derivatives\n", 479 | "92_Sentiment-Driven Trading Strategies_Sentimental Journeys: Trading on Market Mood\n", 480 | "93_Survival Analysis in Finance_Survival of the Fittest: Applying Survival Analysis\n", 481 | "94_Seasonality Effects in Markets_Seasonal Strategies: Navigating Market Seasonality\n", 482 | "95_Liquidity Provision Strategies_Liquid Logic: Mastering Liquidity Provision Strategies\n", 483 | "96_Game Theory in Finance_Financial Foresight: Game Theory in Action\n", 484 | "97_Real Estate Quantitative Analysis_Realty Reality: Quantitative Analysis in Real Estate\n", 485 | "98_Trading Infrastructure Development_Infrastucture Insights: Building Robust Trading Systems\n", 486 | "99_Financial Data Visualization_Visual Wealth: Financial Data Visualization Techniques\n", 487 | "100_High-Frequency Trading_The Need for Speed: Inside High-Frequency Trading\n" 488 | ] 489 | } 490 | ], 491 | "source": [ 492 | "file = open(RAW_TEXT_FILE, \"r\")\n", 493 | "quant_tweets = {}\n", 494 | "\n", 495 | "for line_no, line in enumerate(file.readlines()):\n", 496 | " # start 2nd row to avoid heading and underlines\n", 497 | " if line_no > 1:\n", 498 | " # split on line divisors\n", 499 | " items = line.split('|')\n", 500 | " # capture and ensure int and str formatting\n", 501 | " tweet_no = int(items[1])\n", 502 | " quant_topic = items[2].strip()\n", 503 | " quant_title = items[3].strip().strip('\"')\n", 504 | " # store within dict\n", 505 | " quant_tweets[tweet_no] = {}\n", 506 | " quant_tweets[tweet_no]['topic'] = quant_topic\n", 507 | " quant_tweets[tweet_no]['title'] = quant_title\n", 508 | " # print tweet no, topic and title\n", 509 | " print(f\"{tweet_no}_{quant_topic}_{quant_title}\")\n", 510 | "file.close()\n", 511 | "\n", 512 | "# storing in desired format\n", 513 | "# could directly place processed data location here: TEXT_FILE instead of 'quants_tweets.txt'\n", 514 | "with open('quants_tweets.txt', 'w') as f:\n", 515 | " for tweet_no, tweet_info in quant_tweets.items():\n", 516 | " #Attaching 3 flags at the end which are currently all False\n", 517 | " tweet_repr = str(tweet_no)+'|'+tweet_info['topic']+'|'+tweet_info['title']+'|FALSE|FALSE|FALSE|\\n'\n", 518 | " f.write(tweet_repr)" 519 | ] 520 | }, 521 | { 522 | "cell_type": "markdown", 523 | "id": "4a960f4a-6773-49f1-b579-88db5ec9bea3", 524 | "metadata": {}, 525 | "source": [ 526 | "## Twitter File\n", 527 | "\n", 528 | "We will use a dataclasses to:\n", 529 | "1. store Tweets,\n", 530 | "2. track Track, and\n", 531 | "3. manage a TweetQueue" 532 | ] 533 | }, 534 | { 535 | "cell_type": "code", 536 | "execution_count": 6, 537 | "id": "6459a9f0-36f9-47a5-b686-fc32c017d37e", 538 | "metadata": {}, 539 | "outputs": [], 540 | "source": [ 541 | "from enum import Flag, auto\n", 542 | "from json import dumps, loads\n", 543 | "from dataclasses import dataclass, asdict, field\n", 544 | "\n", 545 | "\n", 546 | "class Boolean(Flag):\n", 547 | " TRUE = True\n", 548 | " FALSE = False\n", 549 | "\n", 550 | "\n", 551 | "class TweetType(Flag):\n", 552 | " SINGLE = auto()\n", 553 | " THREAD = auto()\n", 554 | "\n", 555 | "\n", 556 | "@dataclass\n", 557 | "class Tweet:\n", 558 | " Hook: str\n", 559 | " Intro: str\n", 560 | " Explanation: str\n", 561 | " Application: str\n", 562 | " Closing: str\n", 563 | " Action: str\n", 564 | " Engagement: str\n", 565 | "\n", 566 | " @classmethod\n", 567 | " def from_dict(cls, tweet_d: dict):\n", 568 | " # return class\n", 569 | " return cls(\n", 570 | " Hook=tweet_d[\"Hook\"],\n", 571 | " Intro=tweet_d[\"Intro\"],\n", 572 | " Explanation=tweet_d[\"Explanation\"],\n", 573 | " Application=tweet_d[\"Application\"],\n", 574 | " Closing=tweet_d[\"Closing\"],\n", 575 | " Action=tweet_d[\"Action\"],\n", 576 | " Engagement=tweet_d[\"Engagement\"],\n", 577 | " )\n", 578 | "\n", 579 | " def to_text(self):\n", 580 | " _spaced_response = f\"{self.Hook}\\n{self.Intro}\\n{self.Explanation}\\n{self.Application}\\n{self.Closing}\\n{self.Action}\\n{self.Engagement}\"\n", 581 | " if len(_spaced_response) > 280:\n", 582 | " return f\"{self.Hook}{self.Intro}{self.Explanation}{self.Application}{self.Closing}{self.Action}{self.Engagement}\"\n", 583 | " else:\n", 584 | " return _spaced_response\n", 585 | "\n", 586 | "\n", 587 | "@dataclass\n", 588 | "class TrackTweet:\n", 589 | " \"\"\"Class for keeping track of Tweets\"\"\"\n", 590 | "\n", 591 | " id: int\n", 592 | " topic: str\n", 593 | " title: str\n", 594 | " sent_status: Boolean = Boolean.FALSE\n", 595 | " gen_status: Boolean = Boolean.FALSE\n", 596 | " tweet: Tweet = field(init=False, repr=False)\n", 597 | "\n", 598 | " def __lt__(self, other):\n", 599 | " return (self.sent_status.value, self.id) < (other.sent_status.value, other.id)\n", 600 | "\n", 601 | " @classmethod\n", 602 | " def from_str(cls, tweet_line: str):\n", 603 | " # underscores used to indicate unpacked variables, only used internally\n", 604 | " (\n", 605 | " _id,\n", 606 | " _topic,\n", 607 | " _title,\n", 608 | " _sent_status,\n", 609 | " _gen_status,\n", 610 | " _tweet,\n", 611 | " _next_line,\n", 612 | " ) = tweet_line.split(\"|\")\n", 613 | " # convert status TRUE/FALSE to Enum Representation\n", 614 | " _sent_status_bool = (\n", 615 | " Boolean.TRUE if _sent_status == Boolean.TRUE.name else Boolean.FALSE\n", 616 | " )\n", 617 | " # confirm if tweet already written or not, if so load previously written tweet\n", 618 | " _gen_status_bool = (\n", 619 | " Boolean.TRUE if _gen_status == Boolean.TRUE.name else Boolean.FALSE\n", 620 | " )\n", 621 | " # init class without tweet\n", 622 | " _trackTweet = cls(\n", 623 | " id=int(_id),\n", 624 | " topic=_topic,\n", 625 | " title=_title,\n", 626 | " sent_status=_sent_status_bool,\n", 627 | " gen_status=_gen_status_bool,\n", 628 | " )\n", 629 | "\n", 630 | " if _gen_status_bool:\n", 631 | " # return class with written tweet\n", 632 | " _trackTweet.tweet = Tweet.from_dict(loads(_tweet))\n", 633 | "\n", 634 | " return _trackTweet\n", 635 | "\n", 636 | " def to_str(self):\n", 637 | " _part_1 = f\"{self.id}|{self.topic}|{self.title}|{self.sent_status.name}|{self.gen_status.name}|\"\n", 638 | " _part_2 = (\n", 639 | " f\"{dumps(asdict(self.tweet)) if hasattr(self, 'tweet') else 'FALSE'}|\\n\"\n", 640 | " )\n", 641 | " return _part_1 + _part_2\n", 642 | "\n", 643 | " def update_status(self, new_status: Boolean):\n", 644 | " self.sent_status = new_status\n", 645 | "\n", 646 | "\n", 647 | "@dataclass\n", 648 | "class TweetQueue:\n", 649 | " tweets: list[TrackTweet] = field(default_factory=list)\n", 650 | "\n", 651 | " def __len__(self):\n", 652 | " return len(self.tweets)\n", 653 | "\n", 654 | " def __iter__(self):\n", 655 | " yield from self.tweets\n", 656 | "\n", 657 | " @property\n", 658 | " def tweets_not_sent(self):\n", 659 | " return [tweet for tweet in self.tweets if not tweet.sent_status]\n", 660 | "\n", 661 | " @property\n", 662 | " def tweets_not_generated(self):\n", 663 | " return [tweet for tweet in self.tweets if not tweet.gen_status]\n", 664 | "\n", 665 | " @property\n", 666 | " def tweets_ready_for_sending(self):\n", 667 | " return [\n", 668 | " tweet for tweet in self.tweets if tweet.gen_status and not tweet.sent_status\n", 669 | " ]\n", 670 | "\n", 671 | " def enqueue(self, tweet):\n", 672 | " # print(f\"{tweet.to_str()} will be added.\")\n", 673 | " self.tweets.append(tweet)\n", 674 | "\n", 675 | " def dequeue(self):\n", 676 | " # print(f\"{self.tweets[0].to_str()} will be removed.\")\n", 677 | " return self.tweets.popleft()\n", 678 | "\n", 679 | " @classmethod\n", 680 | " def from_text_file(cls, text_file):\n", 681 | " _tweets = cls()\n", 682 | " for tweet_line in open(text_file, \"r\"):\n", 683 | " tweet = TrackTweet.from_str(tweet_line)\n", 684 | " _tweets.enqueue(tweet)\n", 685 | " return _tweets\n", 686 | "\n", 687 | " def to_text_file(self, text_file):\n", 688 | " with open(text_file, \"w\") as f:\n", 689 | " for tweet in self.tweets:\n", 690 | " tweet_line = tweet.to_str()\n", 691 | " f.write(tweet_line)\n" 692 | ] 693 | }, 694 | { 695 | "cell_type": "markdown", 696 | "id": "66c528ba-4d34-4274-bbbe-0b3e27b1f859", 697 | "metadata": {}, 698 | "source": [ 699 | "## Use Tweet Classes\n", 700 | "\n", 701 | "Let's read in tweet Queue from processed data file.\n", 702 | "\n", 703 | "We will use the iterator we contructed to immediately loop through tweets class attribute" 704 | ] 705 | }, 706 | { 707 | "cell_type": "code", 708 | "execution_count": 7, 709 | "id": "628c9d73-6ea5-4494-bceb-1584561cb085", 710 | "metadata": {}, 711 | "outputs": [ 712 | { 713 | "name": "stdout", 714 | "output_type": "stream", 715 | "text": [ 716 | "TrackTweet(id=1, topic='Time Value of Money', title='Unveiling the Magic of Compounding: Time Value of Money', sent_status=, gen_status=)\n" 717 | ] 718 | } 719 | ], 720 | "source": [ 721 | "tweetQueue = TweetQueue.from_text_file(TEXT_FILE)\n", 722 | "for tweet in tweetQueue:\n", 723 | " print(tweet)\n", 724 | " break" 725 | ] 726 | }, 727 | { 728 | "cell_type": "markdown", 729 | "id": "938bc593-aa6a-46a5-be77-8842ff17970d", 730 | "metadata": {}, 731 | "source": [ 732 | "## Generate Tweets from Data\n", 733 | "\n", 734 | "Putting it all togetehr, let's use the property of our TweetQueue to get latest non generated tweet.\n", 735 | "\n", 736 | "Let's pass the topic and title to our generate response function and extract the tweet to dictionary" 737 | ] 738 | }, 739 | { 740 | "cell_type": "code", 741 | "execution_count": 8, 742 | "id": "72e535f4-39ee-4b2f-a735-683602555341", 743 | "metadata": {}, 744 | "outputs": [ 745 | { 746 | "ename": "IndexError", 747 | "evalue": "list index out of range", 748 | "output_type": "error", 749 | "traceback": [ 750 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 751 | "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", 752 | "Cell \u001b[0;32mIn[8], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m quant_tweet_idea \u001b[38;5;241m=\u001b[39m \u001b[43mtweetQueue\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtweets_not_generated\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\n\u001b[1;32m 2\u001b[0m first_response, short_response \u001b[38;5;241m=\u001b[39m generate_response(llm, quant_topic\u001b[38;5;241m=\u001b[39mquant_tweet_idea\u001b[38;5;241m.\u001b[39mtopic, quant_title\u001b[38;5;241m=\u001b[39mquant_tweet_idea\u001b[38;5;241m.\u001b[39mtitle)\n\u001b[1;32m 3\u001b[0m first_draft \u001b[38;5;241m=\u001b[39m extract_tweet(first_response, key_list)\n", 753 | "\u001b[0;31mIndexError\u001b[0m: list index out of range" 754 | ] 755 | } 756 | ], 757 | "source": [ 758 | "quant_tweet_idea = tweetQueue.tweets_not_generated[0]\n", 759 | "first_response, short_response = generate_response(llm, quant_topic=quant_tweet_idea.topic, quant_title=quant_tweet_idea.title)\n", 760 | "first_draft = extract_tweet(first_response, key_list)\n", 761 | "first_draft" 762 | ] 763 | }, 764 | { 765 | "cell_type": "markdown", 766 | "id": "d4eaa8ee-f1d9-4f37-8c2a-a8014b1a13d4", 767 | "metadata": {}, 768 | "source": [ 769 | "We can then pass the dictionary to create a Tweet Object" 770 | ] 771 | }, 772 | { 773 | "cell_type": "code", 774 | "execution_count": 52, 775 | "id": "1d9404c9-559b-4a91-9dfb-b2af7c8655c2", 776 | "metadata": {}, 777 | "outputs": [ 778 | { 779 | "data": { 780 | "text/plain": [ 781 | "Tweet(Hook='\"Order Book Dynamics: Where the battle of buyers and sellers unfolds, revealing the true market sentiment.\"\\n\\n', Intro='Order Book Dynamics refers to the continuous interplay between buy and sell orders in a financial market, providing valuable insights into market depth and liquidity.\\n\\n', Explanation='The order book is a real-time record of all pending buy and sell orders for a particular asset. It displays the quantity and price at which market participants are willing to buy or sell. As orders are executed, the order book dynamically adjusts, reflecting changes in supply and demand.\\n\\n', Application='Understanding order book dynamics is crucial for market participants, including traders, market makers, and algorithmic trading systems. By analyzing the order book, traders can identify support and resistance levels, gauge market sentiment, and make informed trading decisions. Market makers utilize order book dynamics to provide liquidity and manage their inventory. Algorithmic trading systems leverage order book dynamics to execute trades based on predefined strategies.\\n\\n', Closing='Order book dynamics is the heartbeat of the market, revealing the ebb and flow of supply and demand.\\n\\n', Action='Dive into the fascinating world of order book dynamics and unlock the secrets of market sentiment.\\n\\n', Engagement='How do you use order book dynamics in your trading strategy? #OrderBookDynamics #QuantFinance')" 782 | ] 783 | }, 784 | "execution_count": 52, 785 | "metadata": {}, 786 | "output_type": "execute_result" 787 | } 788 | ], 789 | "source": [ 790 | "Tweet.from_dict(first_draft)" 791 | ] 792 | }, 793 | { 794 | "cell_type": "code", 795 | "execution_count": null, 796 | "id": "45a1818d-ade3-49db-87ea-8d36af1d7ded", 797 | "metadata": {}, 798 | "outputs": [], 799 | "source": [] 800 | } 801 | ], 802 | "metadata": { 803 | "kernelspec": { 804 | "display_name": "Python 3 (ipykernel)", 805 | "language": "python", 806 | "name": "python3" 807 | }, 808 | "language_info": { 809 | "codemirror_mode": { 810 | "name": "ipython", 811 | "version": 3 812 | }, 813 | "file_extension": ".py", 814 | "mimetype": "text/x-python", 815 | "name": "python", 816 | "nbconvert_exporter": "python", 817 | "pygments_lexer": "ipython3", 818 | "version": "3.11.4" 819 | } 820 | }, 821 | "nbformat": 4, 822 | "nbformat_minor": 5 823 | } 824 | -------------------------------------------------------------------------------- /notebooks/quants_tweets.txt: -------------------------------------------------------------------------------- 1 | 1|Time Value of Money|Unveiling the Magic of Compounding: Time Value of Money|FALSE|FALSE|FALSE| 2 | 2|Risk and Return|Playing the Odds: Understanding Risk and Return|FALSE|FALSE|FALSE| 3 | 3|Modern Portfolio Theory|Crafting the Perfect Portfolio: An Intro to MPT|FALSE|FALSE|FALSE| 4 | 4|Black-Scholes Model|The Black-Scholes Legacy: Revolutionizing Option Pricing|FALSE|FALSE|FALSE| 5 | 5|Multifactor Models|Beyond Beta: Exploring Multifactor Models|FALSE|FALSE|FALSE| 6 | 6|Copula Models|Bridging Dependencies: An Insight into Copula Models|FALSE|FALSE|FALSE| 7 | 7|Stochastic Calculus|The Dance of Chance: Delving into Stochastic Calculus|FALSE|FALSE|FALSE| 8 | 8|Ito's Lemma|Ito's Insight: Unpacking Ito's Lemma|FALSE|FALSE|FALSE| 9 | 9|Quantitative Risk Management|Taming Uncertainty: Quantitative Risk Management Essentials|FALSE|FALSE|FALSE| 10 | 10|Simple Moving Average Strategy|Smooth Moves: SMA Trading Strategy Explained|FALSE|FALSE|FALSE| 11 | 11|Backtesting|Rewinding The Market: The Art of Backtesting|FALSE|FALSE|FALSE| 12 | 12|Transaction Costs and Slippage|The Hidden Costs: Navigating Transaction Costs and Slippage|FALSE|FALSE|FALSE| 13 | 13|Portfolio Optimization|Balancing Act: Portfolio Optimization Techniques|FALSE|FALSE|FALSE| 14 | 14|QuantLib Introduction|Toolkit Talk: A Dive into QuantLib|FALSE|FALSE|FALSE| 15 | 15|Implementing Monte Carlo Simulations|Rolling the Dice: Monte Carlo Simulations in Trading|FALSE|FALSE|FALSE| 16 | 16|Time Series Analysis|Decoding Time: An Adventure into Time Series Analysis|FALSE|FALSE|FALSE| 17 | 17|Machine Learning in Finance|The Finance Algorithm: Machine Learning's Role|FALSE|FALSE|FALSE| 18 | 18|Cryptocurrency Quant Strategies|Crypto Conundrums: Quant Strategies in Cryptocurrency Markets|FALSE|FALSE|FALSE| 19 | 19|High-frequency Trading Strategies|Milliseconds to Millions: High-frequency Trading Strategies|FALSE|FALSE|FALSE| 20 | 20|Market Anomalies Analysis|Bizarre Bazaars: Analyzing Market Anomalies|FALSE|FALSE|FALSE| 21 | 21|Financial Crises Analysis|Crash Course: Analyzing Major Financial Crises|FALSE|FALSE|FALSE| 22 | 22|Strategies of Quant Hedge Funds|Quantum Leaps: Strategies of Top Quant Hedge Funds|FALSE|FALSE|FALSE| 23 | 23|Zipline Library Introduction|Zipping Through Data: An Introduction to Zipline Library|FALSE|FALSE|FALSE| 24 | 24|Backtrader Library Introduction|Trade the Code: Getting Started with Backtrader|FALSE|FALSE|FALSE| 25 | 25|Statsmodels Library Introduction|Modeling Market Mysteries with Statsmodels|FALSE|FALSE|FALSE| 26 | 26|Interest Rate Models|Rate of Change: Diving into Interest Rate Models|FALSE|FALSE|FALSE| 27 | 27|Credit Risk Models|Credit Where It's Due: Unveiling Credit Risk Models|FALSE|FALSE|FALSE| 28 | 28|Derivative Pricing|Price Tag on Risk: The World of Derivative Pricing|FALSE|FALSE|FALSE| 29 | 29|Option Pricing|Options Unveiled: The Pricing Paradigm|FALSE|FALSE|FALSE| 30 | 30|Volatility Forecasting|Predicting Pandemonium: Volatility Forecasting Techniques|FALSE|FALSE|FALSE| 31 | 31|Arbitrage Pricing Theory|Free Lunch? Unpacking Arbitrage Pricing Theory|FALSE|FALSE|FALSE| 32 | 32|Behavioral Finance|Mind Over Markets: A Look into Behavioral Finance|FALSE|FALSE|FALSE| 33 | 33|Equity Quant Strategies|Stocks and Quants: Equity Quantitative Strategies|FALSE|FALSE|FALSE| 34 | 34|Fixed Income Quant Strategies|Bonding with Quant: Fixed Income Quantitative Strategies|FALSE|FALSE|FALSE| 35 | 35|Commodities Quant Strategies|Golden Opportunities: Commodities Quantitative Strategies|FALSE|FALSE|FALSE| 36 | 36|Forex Quant Strategies|Currency Code: Forex Quantitative Strategies|FALSE|FALSE|FALSE| 37 | 37|Asset Allocation Strategies|The Allocation Equation: Asset Allocation Strategies|FALSE|FALSE|FALSE| 38 | 38|Liquidity Risk Management|Liquid or Illiquid? Navigating Liquidity Risk|FALSE|FALSE|FALSE| 39 | 39|Performance Measurement|Measuring Mastery: Performance Measurement in Quant Finance|FALSE|FALSE|FALSE| 40 | 40|Hedge Fund Structure and Strategies|Hedge Fund Hierarchy: Structure and Strategies Uncovered|FALSE|FALSE|FALSE| 41 | 41|Asset Pricing Models|Valuing Varieties: A Look at Asset Pricing Models|FALSE|FALSE|FALSE| 42 | 42|Market Microstructure|Market Mosaic: Delving into Market Microstructure|FALSE|FALSE|FALSE| 43 | 43|Algorithmic Trading Risks|Algo Angst: Navigating Risks in Algorithmic Trading|FALSE|FALSE|FALSE| 44 | 44|Regulatory Environment|Rulebook of the Ruled: Understanding Financial Regulation|FALSE|FALSE|FALSE| 45 | 45|Portfolio Performance Analysis|Portfolio's Proof: Delving into Performance Analysis|FALSE|FALSE|FALSE| 46 | 46|Value at Risk (VaR)|VaR's Vantage: Unpacking Value at Risk|FALSE|FALSE|FALSE| 47 | 47|Stress Testing|Financial Fitness: The Essence of Stress Testing|FALSE|FALSE|FALSE| 48 | 48|Exotic Options Pricing|Beyond Vanilla: Pricing Exotic Options|FALSE|FALSE|FALSE| 49 | 49|Sentiment Analysis in Finance|Feel the Market's Pulse: Sentiment Analysis Unveiled|FALSE|FALSE|FALSE| 50 | 50|Systematic Trading Strategies|Systematic Success: Exploring Systematic Trading Strategies|FALSE|FALSE|FALSE| 51 | 51|Trading Psychology|Mind over Markets: Unpacking Trading Psychology|FALSE|FALSE|FALSE| 52 | 52|Alternative Data in Finance|Alt Data Alchemy: The New Gold in Finance|FALSE|FALSE|FALSE| 53 | 53|ETF Trading Strategies|ETF Expeditions: Unveiling Trading Strategies|FALSE|FALSE|FALSE| 54 | 54|Quantitative Model Validation|Model Marvel or Mirage: The Art of Quant Model Validation|FALSE|FALSE|FALSE| 55 | 55|Factor Investing|Factor Feast: Diving into Factor Investing|FALSE|FALSE|FALSE| 56 | 56|Futures and Forwards|Future-Forward Finance: Exploring Futures and Forwards|FALSE|FALSE|FALSE| 57 | 57|Swap Contracts|Switcheroo: Unraveling Swap Contracts|FALSE|FALSE|FALSE| 58 | 58|Risk Parity Strategies|Balancing Act: Delving into Risk Parity Strategies|FALSE|FALSE|FALSE| 59 | 59|Technical Analysis|Charting the Course: Technical Analysis Techniques|FALSE|FALSE|FALSE| 60 | 60|Event-Driven Trading Strategies|Eventful Earnings: Mastering Event-Driven Trading Strategies|FALSE|FALSE|FALSE| 61 | 61|Fundamental Analysis|Beyond Numbers: The Essence of Fundamental Analysis|FALSE|FALSE|FALSE| 62 | 62|Statistical Arbitrage|Statistical Stakes: A Dive into Statistical Arbitrage|FALSE|FALSE|FALSE| 63 | 63|Portfolio Construction|Building Financial Fortresses: Portfolio Construction Essentials|FALSE|FALSE|FALSE| 64 | 64|High-Frequency Trading Technology|Speed Demons: Tech Behind High-Frequency Trading|FALSE|FALSE|FALSE| 65 | 65|Momentum Trading Strategies|Momentum Mysteries: Unveiling Momentum Trading Strategies|FALSE|FALSE|FALSE| 66 | 66|Market Making Strategies|Market Maestro: Mastering Market Making Strategies|FALSE|FALSE|FALSE| 67 | 67|Pairs Trading|Twins of Trade: Pairs Trading Explained|FALSE|FALSE|FALSE| 68 | 68|Machine Learning Algorithm Tuning|Tuning the Financial Tune: ML Algorithm Tuning in Finance|FALSE|FALSE|FALSE| 69 | 69|Neural Networks in Finance|Financial Foresight: Neural Networks in Action|FALSE|FALSE|FALSE| 70 | 70|Reinforcement Learning in Trading|Rewarding Routines: Reinforcement Learning in Trading|FALSE|FALSE|FALSE| 71 | 71|Blockchain Technology|Block by Block: Unpacking Blockchain Technology|FALSE|FALSE|FALSE| 72 | 72|Smart Contracts|Contractual Clarity: Delving into Smart Contracts|FALSE|FALSE|FALSE| 73 | 73|Quantitative Easing Impact|Easing into Economics: Impact of Quantitative Easing|FALSE|FALSE|FALSE| 74 | 74|Inflation Hedging Strategies|Inflation Insulation: Hedging Strategies Explored|FALSE|FALSE|FALSE| 75 | 75|Central Bank Policies|Banking on Policy: Unpacking Central Bank Moves|FALSE|FALSE|FALSE| 76 | 76|Financial Data Cleaning and Processing|Data Detox: Cleaning and Processing Financial Data|FALSE|FALSE|FALSE| 77 | 77|Quantitative Finance Career Paths|Quant Quest: Exploring Career Paths in Quantitative Finance|FALSE|FALSE|FALSE| 78 | 78|Real-world Quantitative Finance Projects|From Theory to Thriving: Real-world Quant Projects|FALSE|FALSE|FALSE| 79 | 79|Financial Ethics and Compliance|Ethical Earnings: Finance Ethics and Compliance|FALSE|FALSE|FALSE| 80 | 80|Trading Platform Development|Platform Power-play: Developing Your Trading Platform|FALSE|FALSE|FALSE| 81 | 81|Python Libraries for Finance|Library Lore: Python Libraries Every Quant Should Know|FALSE|FALSE|FALSE| 82 | 82|Order Book Dynamics|Booked on Books: Understanding Order Book Dynamics|FALSE|FALSE|FALSE| 83 | 83|Derivatives Hedging Strategies|Derivative Defenses: Mastering Hedging Strategies|FALSE|FALSE|FALSE| 84 | 84|Quantitative Finance Interviews Prep|Quant Quizzing: Acing Quantitative Finance Interviews|FALSE|FALSE|FALSE| 85 | 85|Financial Networks Analysis|Network of Net-worth: Unveiling Financial Networks|FALSE|FALSE|FALSE| 86 | 86|Market Impact Models|Impactful Insights: Delving into Market Impact Models|FALSE|FALSE|FALSE| 87 | 87|Trading Signal Generation|Signal Success: Generating and Evaluating Trading Signals|FALSE|FALSE|FALSE| 88 | 88|Latency in Trading Systems|Latent Lessons: The Role of Latency in Trading Systems|FALSE|FALSE|FALSE| 89 | 89|Market Anomalies Exploitation|Anomalous Achievements: Exploiting Market Anomalies|FALSE|FALSE|FALSE| 90 | 90|Trading System Evaluation|Systematic Scrutiny: Evaluating Trading Systems|FALSE|FALSE|FALSE| 91 | 91|Credit Derivatives|Credit Chronicles: An Overview of Credit Derivatives|FALSE|FALSE|FALSE| 92 | 92|Sentiment-Driven Trading Strategies|Sentimental Journeys: Trading on Market Mood|FALSE|FALSE|FALSE| 93 | 93|Survival Analysis in Finance|Survival of the Fittest: Applying Survival Analysis|FALSE|FALSE|FALSE| 94 | 94|Seasonality Effects in Markets|Seasonal Strategies: Navigating Market Seasonality|FALSE|FALSE|FALSE| 95 | 95|Liquidity Provision Strategies|Liquid Logic: Mastering Liquidity Provision Strategies|FALSE|FALSE|FALSE| 96 | 96|Game Theory in Finance|Financial Foresight: Game Theory in Action|FALSE|FALSE|FALSE| 97 | 97|Real Estate Quantitative Analysis|Realty Reality: Quantitative Analysis in Real Estate|FALSE|FALSE|FALSE| 98 | 98|Trading Infrastructure Development|Infrastucture Insights: Building Robust Trading Systems|FALSE|FALSE|FALSE| 99 | 99|Financial Data Visualization|Visual Wealth: Financial Data Visualization Techniques|FALSE|FALSE|FALSE| 100 | 100|High-Frequency Trading|The Need for Speed: Inside High-Frequency Trading|FALSE|FALSE|FALSE| 101 | -------------------------------------------------------------------------------- /notebooks/quants_tweets_2.txt: -------------------------------------------------------------------------------- 1 | 101|Time Value of Money|Understanding the Time Value of Money in Quant Finance|FALSE|FALSE|FALSE| 2 | 102|Risk and Return|Quantifying Risk and Return|FALSE|FALSE|FALSE| 3 | 103|Modern Portfolio Theory|Mastering Modern Portfolio Theory|FALSE|FALSE|FALSE| 4 | 104|Black-Scholes Model|Black-Scholes Model: The ABCs of Option Pricing|FALSE|FALSE|FALSE| 5 | 105|Multifactor Models|Exploring Multifactor Models in Finance|FALSE|FALSE|FALSE| 6 | 106|Copula Models|Copula Models: The Backbone of Financial Engineering|FALSE|FALSE|FALSE| 7 | 107|Stochastic Calculus|Stochastic Calculus for Finance: A Primer|FALSE|FALSE|FALSE| 8 | 108|Ito’s Lemma|Ito's Lemma Explained|FALSE|FALSE|FALSE| 9 | 109|Quantitative Risk Management|Techniques in Quantitative Risk Management|FALSE|FALSE|FALSE| 10 | 110|Simple Moving Average|Building a Simple Moving Average Trading Strategy|FALSE|FALSE|FALSE| 11 | 111|Backtesting|Introduction to Backtesting and its Pitfalls|FALSE|FALSE|FALSE| 12 | 112|Transaction Costs|Incorporating Transaction Costs in Trading Models|FALSE|FALSE|FALSE| 13 | 113|Slippage|Understanding and Accounting for Slippage|FALSE|FALSE|FALSE| 14 | 114|Portfolio Optimization|Portfolio Optimization Techniques|FALSE|FALSE|FALSE| 15 | 115|QuantLib|Introduction to QuantLib|FALSE|FALSE|FALSE| 16 | 116|Zipline|Getting Started with Zipline|FALSE|FALSE|FALSE| 17 | 117|Backtrader|Algorithmic Trading with Backtrader|FALSE|FALSE|FALSE| 18 | 118|Monte Carlo Simulations|Implementing Monte Carlo Simulations using Python|FALSE|FALSE|FALSE| 19 | 119|Time Series Analysis|Time Series Analysis with Statsmodels|FALSE|FALSE|FALSE| 20 | 120|Machine Learning|Machine Learning in Quantitative Finance|FALSE|FALSE|FALSE| 21 | 121|Cryptocurrency|Cryptocurrency Trading Strategies for Quants|FALSE|FALSE|FALSE| 22 | 122|High-Frequency Trading|High-Frequency Trading Strategies|FALSE|FALSE|FALSE| 23 | 123|Market Anomalies|Analyzing Famous Market Anomalies|FALSE|FALSE|FALSE| 24 | 124|Financial Crises|Breaking Down Financial Crises: A Quant Perspective|FALSE|FALSE|FALSE| 25 | 125|Hedge Funds|Exploring Hedge Fund Strategies: Renaissance Technologies|FALSE|FALSE|FALSE| 26 | 126|Algorithmic Trading Basics|Algorithmic Trading: A Comprehensive Guide|FALSE|FALSE|FALSE| 27 | 127|Behavioral Finance|Behavioral Finance and Quant Strategies|FALSE|FALSE|FALSE| 28 | 128|Volatility Modeling|Understanding Volatility: Models and Implications|FALSE|FALSE|FALSE| 29 | 129|Bayesian Methods|Bayesian Methods in Finance|FALSE|FALSE|FALSE| 30 | 130|Neural Networks|Neural Networks in Finance: A Quick Start Guide|FALSE|FALSE|FALSE| 31 | 131|Option Greeks|Understanding Option Greeks: Delta, Gamma, Vega|FALSE|FALSE|FALSE| 32 | 132|Value at Risk|Calculating Value at Risk: Methods and Models|FALSE|FALSE|FALSE| 33 | 133|Real Options|Real Options in Corporate Finance|FALSE|FALSE|FALSE| 34 | 134|Natural Language Processing|NLP in Quant Finance: Sentiment Analysis|FALSE|FALSE|FALSE| 35 | 135|Event-Driven Strategies|Event-Driven Trading Strategies|FALSE|FALSE|FALSE| 36 | 136|Utility Theory|Utility Theory in Portfolio Management|FALSE|FALSE|FALSE| 37 | 137|Mean Reversion|Mean Reversion Strategies: Theory and Practice|FALSE|FALSE|FALSE| 38 | 138|GARCH Models|Introduction to GARCH Models|FALSE|FALSE|FALSE| 39 | 139|CAPM|Capital Asset Pricing Model: A Quant's View|FALSE|FALSE|FALSE| 40 | 140|Cointegration|Understanding Cointegration: A Quant Approach|FALSE|FALSE|FALSE| 41 | 141|ARIMA Models|ARIMA Models in Time Series Forecasting|FALSE|FALSE|FALSE| 42 | 142|Pairs Trading|Mastering Pairs Trading: Strategies and Techniques|FALSE|FALSE|FALSE| 43 | 143|Simulation Methods|Simulation Methods in Quant Finance|FALSE|FALSE|FALSE| 44 | 144|CVA and Counterparty Risk|CVA and Counterparty Risk: A Quantitative Analysis|FALSE|FALSE|FALSE| 45 | 145|Dynamic Hedging|Dynamic Hedging: Techniques and Strategies|FALSE|FALSE|FALSE| 46 | 146|Quantitative Value|Quantitative Value: A Practitioner’s Guide|FALSE|FALSE|FALSE| 47 | 147|Option Strategies|Popular Option Strategies: A Quantitative Review|FALSE|FALSE|FALSE| 48 | 148|Term Structure of Interest Rates|Understanding the Term Structure of Interest Rates|FALSE|FALSE|FALSE| 49 | 149|Markov Chains|Markov Chains in Quantitative Finance|FALSE|FALSE|FALSE| 50 | 150|Fixed Income Securities|Quantitative Approaches to Fixed Income Securities|FALSE|FALSE|FALSE| 51 | 151|Credit Risk|Quantitative Methods for Credit Risk Analysis|FALSE|FALSE|FALSE| 52 | 152|Value Investing|A Quantitative Approach to Value Investing|FALSE|FALSE|FALSE| 53 | 153|Reinforcement Learning|Using Reinforcement Learning in Trading Strategies|FALSE|FALSE|FALSE| 54 | 154|Econometrics|Introduction to Econometric Models for Quants|FALSE|FALSE|FALSE| 55 | 155|Sentiment Analysis|Quantifying Market Sentiment: A Guide|FALSE|FALSE|FALSE| 56 | 156|Technical Indicators|How to Use RSI and MACD in Algorithmic Trading|FALSE|FALSE|FALSE| 57 | 157|Market Microstructure|Understanding Market Microstructure|FALSE|FALSE|FALSE| 58 | 158|Bid-Ask Spread|The Quantitative Analysis of Bid-Ask Spreads|FALSE|FALSE|FALSE| 59 | 159|Liquidity|Quantifying Liquidity: Methods and Measures|FALSE|FALSE|FALSE| 60 | 160|Fuzzy Logic|Using Fuzzy Logic in Quantitative Finance|FALSE|FALSE|FALSE| 61 | 161|Fractional Brownian Motion|Fractional Brownian Motion in Finance: An Introduction|FALSE|FALSE|FALSE| 62 | 162|Long-Short Strategies|Long-Short Strategies: A Quant Approach|FALSE|FALSE|FALSE| 63 | 163|Convex Optimization|Convex Optimization in Quant Finance|FALSE|FALSE|FALSE| 64 | 164|ARDL Models|AutoRegressive Distributed Lag (ARDL) Models in Finance|FALSE|FALSE|FALSE| 65 | 165|ETF Arbitrage|Understanding ETF Arbitrage: A Quantitative Guide|FALSE|FALSE|FALSE| 66 | 166|Bootstrap Methods|Bootstrap Methods in Finance|FALSE|FALSE|FALSE| 67 | 167|Quantitative Strategy Evaluation|Evaluating Quant Strategies: Key Metrics|FALSE|FALSE|FALSE| 68 | 168|Kelly Criterion|Using the Kelly Criterion in Trading|FALSE|FALSE|FALSE| 69 | 169|Dark Pools|Dark Pools: A Quantitative Perspective|FALSE|FALSE|FALSE| 70 | 170|Hedge Fund Replication|Hedge Fund Replication: Quantitative Methods|FALSE|FALSE|FALSE| 71 | 171|Data Snooping|Data Snooping: A Quant’s Guide to Avoiding Bias|FALSE|FALSE|FALSE| 72 | 172|Non-linear Models|Non-linear Models in Quantitative Finance|FALSE|FALSE|FALSE| 73 | 173|Heteroskedasticity|Dealing with Heteroskedasticity in Financial Data|FALSE|FALSE|FALSE| 74 | 174|Statistical Arbitrage|Understanding Statistical Arbitrage|FALSE|FALSE|FALSE| 75 | 175|Decision Trees|Applying Decision Trees in Finance|FALSE|FALSE|FALSE| 76 | 176|Futures and Forwards|Quantitative Analysis of Futures and Forwards|FALSE|FALSE|FALSE| 77 | 177|Leverage|Understanding Leverage: A Quantitative Analysis|FALSE|FALSE|FALSE| 78 | 178|Fundamentals of ETFs|The Fundamentals of ETFs: A Quant’s Perspective|FALSE|FALSE|FALSE| 79 | 179|Trading Psychology|Trading Psychology and Quant Strategies|FALSE|FALSE|FALSE| 80 | 180|Copula-based Dependency|Understanding Copula-based Dependency in Finance|FALSE|FALSE|FALSE| 81 | 181|Jump-diffusion Models|Jump-diffusion Models in Option Pricing|FALSE|FALSE|FALSE| 82 | 182|K-means Clustering|K-means Clustering in Portfolio Management|FALSE|FALSE|FALSE| 83 | 183|Spline Methods|Spline Methods for Curve Fitting in Finance|FALSE|FALSE|FALSE| 84 | 184|Quants in Investment Banking|Roles of Quants in Investment Banking|FALSE|FALSE|FALSE| 85 | 185|Interest Rate Swaps|Quantitative Analysis of Interest Rate Swaps|FALSE|FALSE|FALSE| 86 | 186|Energy Derivatives|Quantitative Models for Energy Derivatives|FALSE|FALSE|FALSE| 87 | 187|Exotic Options|Pricing Exotic Options: A Quantitative Guide|FALSE|FALSE|FALSE| 88 | 188|Student-t Distribution|Student-t Distribution in Quant Finance|FALSE|FALSE|FALSE| 89 | 189|Forecasting Volatility|Forecasting Volatility: Models and Methods|FALSE|FALSE|FALSE| 90 | 190|Career Paths|Career Paths in Quantitative Finance|FALSE|FALSE|FALSE| 91 | 191|PCA in Finance|Principal Component Analysis in Finance|FALSE|FALSE|FALSE| 92 | 192|ETF Mechanics|ETF Mechanics: Creation and Redemption|FALSE|FALSE|FALSE| 93 | 193|Trend Following|Trend Following Strategies: A Quantitative Approach|FALSE|FALSE|FALSE| 94 | 194|Quantitative Momentum|Quantitative Momentum: Strategies and Metrics|FALSE|FALSE|FALSE| 95 | 195|Socially Responsible Investing|Quantitative Methods in Socially Responsible Investing|FALSE|FALSE|FALSE| 96 | 196|Risk Parity|Understanding Risk Parity in Portfolio Management|FALSE|FALSE|FALSE| 97 | 197|Commodity Trading|Quantitative Models for Commodity Trading|FALSE|FALSE|FALSE| 98 | 198|Autocorrelation|Detecting Autocorrelation in Financial Time Series|FALSE|FALSE|FALSE| 99 | 199|Machine Learning Series|Machine Learning in Finance: A Multi-part Series|FALSE|FALSE|FALSE| 100 | 200|Python for Quant Finance Series|Python for Quant Finance: A Comprehensive Guide|FALSE|FALSE|FALSE| 101 | -------------------------------------------------------------------------------- /quantpy_feed/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheQuantPy/quantpy-twitter-bot/1f7bb24d9d096faf57cc159df9be99c996bbada1/quantpy_feed/__init__.py -------------------------------------------------------------------------------- /quantpy_feed/call_openai.py: -------------------------------------------------------------------------------- 1 | from langchain.chat_models import ChatOpenAI 2 | from langchain.prompts import ( 3 | ChatPromptTemplate, 4 | SystemMessagePromptTemplate, 5 | AIMessagePromptTemplate, 6 | HumanMessagePromptTemplate, 7 | ) 8 | 9 | 10 | def generate_response( 11 | llm: ChatOpenAI, quant_topic: str, quant_title: str 12 | ) -> tuple[str, str]: 13 | """Generate AI Twitter Content for QuantPy Twitter Account 14 | 15 | Parameters: 16 | - llm: pre-trained ChatOpenAi large language model 17 | - quant_topic: Topic in Quant Finance 18 | - quant_topic: Topic in Quant Finance 19 | 20 | Returns: 21 | - tuple[long response,short reposonse]: Chat GPT long and short responses 22 | """ 23 | # System Template for LLM to follow 24 | system_template = """ 25 | You are an incredibly wise and smart quantitative analyst that lives and breathes the world of quantitative finance. 26 | Your goal is to writing short-form content for twitter given a `topic` in the area of quantitative finance and a `title` from the user. 27 | 28 | % RESPONSE TONE: 29 | 30 | - Your response should be given in an active voice and be opinionated 31 | - Your tone should be serious w/ a hint of wit and sarcasm 32 | 33 | % RESPONSE FORMAT: 34 | 35 | - Be extremely clear and concise 36 | - Respond with phrases no longer than two sentences 37 | - Do not respond with emojis 38 | 39 | % RESPONSE CONTENT: 40 | 41 | - Include specific examples of where this is used in the quantitative finance space 42 | - If you don't have an answer, say, "Sorry, I'll have to ask the Quant Finance Gods!" 43 | 44 | % RESPONSE TEMPLATE: 45 | 46 | - Here is the response structure: 47 | Hook: Captivate with a one-liner. 48 | Intro: Briefly introduce the topic. 49 | Explanation: Simplify the core idea. 50 | Application: Note real-world relevance. 51 | Closing: Reflective one-liner. 52 | Action: Short engagement call. 53 | Engagement: Quick question. 54 | 55 | """ 56 | # system prompt template to follow 57 | system_message_prompt = SystemMessagePromptTemplate.from_template(system_template) 58 | 59 | # human template for input 60 | human_template = "topic to write about is {topic}, and the title will be {title}. Keep the total response under 200 words total!" 61 | human_message_prompt = HumanMessagePromptTemplate.from_template( 62 | human_template, input_variables=["topic", "title"] 63 | ) 64 | 65 | # chat prompt template construction 66 | chat_prompt = ChatPromptTemplate.from_messages( 67 | [system_message_prompt, human_message_prompt] 68 | ) 69 | 70 | # get a completed chat using formatted template with topic and title 71 | final_prompt = chat_prompt.format_prompt( 72 | topic=quant_topic, title=quant_title 73 | ).to_messages() 74 | 75 | # pass template through llm and extract content attribute 76 | first_response = llm(final_prompt).content 77 | 78 | # construct AI template, to pass back OpenAI response 79 | ai_message_prompt = AIMessagePromptTemplate.from_template(first_response) 80 | 81 | # additional prompt to remind ChatGPT of length requirement 82 | reminder_template = "This was good, but way too long, please make your response much more concise and much shorter! Make phrases no longer than 15 words in total. Please maintain the existing template." 83 | reminder_prompt = HumanMessagePromptTemplate.from_template(reminder_template) 84 | 85 | # chat prompt template construction with additional AI response and length reminder 86 | chat_prompt2 = ChatPromptTemplate.from_messages( 87 | [system_message_prompt, human_template, ai_message_prompt, reminder_prompt] 88 | ) 89 | 90 | # get a completed chat using formatted template with topic and title 91 | final_prompt = chat_prompt2.format_prompt( 92 | topic=quant_topic, title=quant_title 93 | ).to_messages() 94 | 95 | # pass template through llm and extract content attribute 96 | short_response = llm(final_prompt).content 97 | 98 | return first_response, short_response 99 | -------------------------------------------------------------------------------- /quantpy_feed/process_tweets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import time 4 | import logging 5 | from dotenv import load_dotenv 6 | from langchain.chat_models import ChatOpenAI 7 | 8 | if __name__ == "__main__": 9 | # module being called directly, use absolute path 10 | from call_openai import generate_response 11 | from twitter import TweetQueue, Tweet, Boolean 12 | 13 | else: 14 | # module being called as package, use relative paths 15 | from .call_openai import generate_response 16 | from .twitter import TweetQueue, Tweet, Boolean 17 | 18 | load_dotenv() 19 | 20 | OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") 21 | 22 | # Setting Variables 23 | CUR_DIR = os.path.dirname(os.path.abspath(__file__)) 24 | APP_DIR = os.path.abspath(os.path.join(CUR_DIR, os.pardir)) 25 | LOG_FILE = os.path.join(APP_DIR, "twitter-bot.log") 26 | TEXT_FILE = os.path.join(APP_DIR, "data/processed/quants_tweets.txt") 27 | 28 | # set up logging to file 29 | logging.basicConfig( 30 | level=logging.INFO, 31 | format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s", 32 | datefmt="%y-%m-%d %H:%M", 33 | filename=LOG_FILE, 34 | filemode="a", 35 | ) 36 | 37 | 38 | count_length = lambda d: sum(len(d[val]) for val in d) 39 | count_words = lambda d: sum(len(re.findall(r"\w+", d[val])) for val in d) 40 | key_list = [ 41 | "Hook", 42 | "Intro", 43 | "Explanation", 44 | "Application", 45 | "Closing", 46 | "Action", 47 | "Engagement", 48 | ] 49 | 50 | 51 | def extract_tweet(openai_tweet: str, key_list: list) -> dict: 52 | """Creates dictionary from Openai response using keyword template 53 | 54 | Parameters: 55 | - openai_tweet: 56 | - key_list: list key words used for searching reponse template 57 | 58 | Returns: 59 | - dictionary: templated tweet 60 | """ 61 | template = {} 62 | # Iterate through key list 63 | for i, key in enumerate(key_list): 64 | # find starting position 65 | start = openai_tweet.find(key_list[i]) + len(key_list[i]) + 2 66 | if i != len(key_list) - 1: 67 | # using ending position, subset str and append to template 68 | end = openai_tweet.find(key_list[i + 1]) 69 | line = openai_tweet[start:end] 70 | template[key_list[i]] = line 71 | else: 72 | # if final word in list, only subsection by start word 73 | template[key_list[i]] = openai_tweet[start:] 74 | return template 75 | 76 | 77 | def generate_tweets(llm: ChatOpenAI, tweetQueue: TweetQueue, text_file: str): 78 | for quant_tweet_track in tweetQueue.tweets_not_generated: 79 | logging.info(5 * "*" + "Tweet to Gen" + 5 * "*") 80 | logging.info(quant_tweet_track) 81 | first_response, short_response = generate_response( 82 | llm, 83 | quant_topic=quant_tweet_track.topic, 84 | quant_title=quant_tweet_track.title, 85 | ) 86 | logging.info(5 * "*" + "First Draft" + 5 * "*") 87 | first_draft = extract_tweet(first_response, key_list) 88 | logging.info( 89 | f"Content Length: {count_length(first_draft)} Tweet Dict {first_draft}" 90 | ) 91 | logging.info(5 * "*" + "Second Draft" + 5 * "*") 92 | short_response = extract_tweet(short_response, key_list) 93 | logging.info( 94 | f"Content Length: {count_length(short_response)} Tweet Dict {short_response}" 95 | ) 96 | 97 | final_tweet = {} 98 | for key, val in first_draft.items(): 99 | if len(val) < 280: 100 | final_tweet[key] = val 101 | 102 | elif len(short_response[key]) < 280: 103 | final_tweet[key] = short_response[key] 104 | 105 | else: 106 | final_tweet[key] = short_response[key][:270] 107 | logging.info(f"Value issue with Tweet {key}, too long") 108 | 109 | quant_tweet_track.tweet = Tweet.from_dict(final_tweet) 110 | quant_tweet_track.update_gen_status(Boolean.TRUE) 111 | 112 | tweetQueue.to_text_file(text_file) 113 | 114 | logging.info(50 * "-") 115 | time.sleep(25) 116 | 117 | 118 | def search_next_tweet(tweetQueue: TweetQueue): 119 | if ( 120 | len(tweetQueue.tweets_not_generated) == 0 121 | and len(tweetQueue.tweets_ready_for_sending) == 0 122 | ): 123 | logging.warning(ValueError("Need to create more tweet data")) 124 | raise ValueError("Need to create more tweet data") 125 | else: 126 | tweetQueue.tweets.sort(reverse=False, key=lambda tweet: tweet.id) 127 | quant_tweet = tweetQueue.tweets_not_sent[0] 128 | return quant_tweet 129 | 130 | 131 | if __name__ == "__main__": 132 | # First step is to import file of topics and ides into TweetQueue 133 | text_file = TEXT_FILE 134 | tweetQueue = TweetQueue.from_text_file(text_file) 135 | 136 | llm = ChatOpenAI( 137 | temperature=0.3, 138 | openai_api_key=OPENAI_API_KEY, 139 | model_name="gpt-3.5-turbo-0613", 140 | ) 141 | 142 | generate_tweets(llm, tweetQueue, text_file) 143 | 144 | tweetQueue.to_text_file(text_file) 145 | -------------------------------------------------------------------------------- /quantpy_feed/twitter.py: -------------------------------------------------------------------------------- 1 | from enum import Flag, auto 2 | from json import dumps, loads 3 | from dataclasses import dataclass, asdict, field 4 | 5 | 6 | class Boolean(Flag): 7 | TRUE = True 8 | FALSE = False 9 | 10 | 11 | class TweetType(Flag): 12 | SINGLE = auto() 13 | THREAD = auto() 14 | 15 | 16 | @dataclass 17 | class Tweet: 18 | """Class for Tweets in desired OpenAI Prompt Template""" 19 | 20 | Hook: str 21 | Intro: str 22 | Explanation: str 23 | Application: str 24 | Closing: str 25 | Action: str 26 | Engagement: str 27 | 28 | @classmethod 29 | def from_dict(cls, tweet_d: dict): 30 | # return class from dictionary 31 | return cls( 32 | Hook=tweet_d["Hook"], 33 | Intro=tweet_d["Intro"], 34 | Explanation=tweet_d["Explanation"], 35 | Application=tweet_d["Application"], 36 | Closing=tweet_d["Closing"], 37 | Action=tweet_d["Action"], 38 | Engagement=tweet_d["Engagement"], 39 | ) 40 | 41 | def to_text(self): 42 | # return text to send directly to twitter 43 | _spaced_response = f"{self.Hook}\n{self.Intro}\n{self.Explanation}\n{self.Application}\n{self.Closing}\n{self.Action}\n{self.Engagement}" 44 | if len(_spaced_response) > 280: 45 | return f"{self.Hook}{self.Intro}{self.Explanation}{self.Application}{self.Closing}{self.Action}{self.Engagement}" 46 | else: 47 | return _spaced_response 48 | 49 | 50 | @dataclass 51 | class TrackTweet: 52 | """Class for Tracking Tweets Status in Process Pipeline""" 53 | 54 | id: int 55 | topic: str 56 | title: str 57 | sent_status: Boolean = Boolean.FALSE 58 | gen_status: Boolean = Boolean.FALSE 59 | tweet: Tweet = field(init=False, repr=False) 60 | 61 | def __lt__(self, other): 62 | return (self.sent_status.value, self.id) < (other.sent_status.value, other.id) 63 | 64 | @classmethod 65 | def from_str(cls, tweet_line: str): 66 | """Generate TrackTweet from String""" 67 | # underscores used to indicate unpacked variables, only used internally 68 | ( 69 | _id, 70 | _topic, 71 | _title, 72 | _sent_status, 73 | _gen_status, 74 | _tweet, 75 | _next_line, 76 | ) = tweet_line.split("|") 77 | # convert status TRUE/FALSE to Enum Representation 78 | _sent_status_bool = ( 79 | Boolean.TRUE if _sent_status == Boolean.TRUE.name else Boolean.FALSE 80 | ) 81 | # confirm if tweet already written or not, if so load previously written tweet 82 | _gen_status_bool = ( 83 | Boolean.TRUE if _gen_status == Boolean.TRUE.name else Boolean.FALSE 84 | ) 85 | # init class without tweet 86 | _trackTweet = cls( 87 | id=int(_id), 88 | topic=_topic, 89 | title=_title, 90 | sent_status=_sent_status_bool, 91 | gen_status=_gen_status_bool, 92 | ) 93 | 94 | if _gen_status_bool: 95 | # return class with written tweet 96 | _trackTweet.tweet = Tweet.from_dict(loads(_tweet)) 97 | 98 | return _trackTweet 99 | 100 | def to_str(self): 101 | """return string that will be saved down as line within text file""" 102 | _part_1 = f"{self.id}|{self.topic}|{self.title}|{self.sent_status.name}|{self.gen_status.name}|" 103 | _part_2 = ( 104 | f"{dumps(asdict(self.tweet)) if hasattr(self, 'tweet') else 'FALSE'}|\n" 105 | ) 106 | return _part_1 + _part_2 107 | 108 | def update_sent_status(self, new_status: Boolean): 109 | """update sent status""" 110 | self.sent_status = new_status 111 | 112 | def update_gen_status(self, new_status: Boolean): 113 | """update sent status""" 114 | self.gen_status = new_status 115 | 116 | 117 | @dataclass 118 | class TweetQueue: 119 | """Class for managing Tweet Pipeline - Processing, Generating, Posting""" 120 | 121 | tweets: list[TrackTweet] = field(default_factory=list) 122 | 123 | def __len__(self): 124 | return len(self.tweets) 125 | 126 | def __iter__(self): 127 | yield from self.tweets 128 | 129 | @property 130 | def tweets_not_sent(self): 131 | return [tweet for tweet in self.tweets if not tweet.sent_status] 132 | 133 | @property 134 | def tweets_not_generated(self): 135 | return [tweet for tweet in self.tweets if not tweet.gen_status] 136 | 137 | @property 138 | def tweets_ready_for_sending(self): 139 | return [ 140 | tweet for tweet in self.tweets if tweet.gen_status and not tweet.sent_status 141 | ] 142 | 143 | def enqueue(self, tweet): 144 | # print(f"{tweet.to_str()} will be added.") 145 | self.tweets.append(tweet) 146 | 147 | def dequeue(self): 148 | # print(f"{self.tweets[0].to_str()} will be removed.") 149 | return self.tweets.popleft() 150 | 151 | @classmethod 152 | def from_text_file(cls, text_file): 153 | _tweets = cls() 154 | for tweet_line in open(text_file, "r"): 155 | tweet = TrackTweet.from_str(tweet_line) 156 | _tweets.enqueue(tweet) 157 | return _tweets 158 | 159 | def to_text_file(self, text_file): 160 | with open(text_file, "w") as f: 161 | for tweet in self.tweets: 162 | tweet_line = tweet.to_str() 163 | f.write(tweet_line) 164 | -------------------------------------------------------------------------------- /quantpy_feed/twitter_feed_bot.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tweepy 3 | import logging 4 | from dataclasses import asdict 5 | from langchain.chat_models import ChatOpenAI 6 | 7 | if __name__ == "__main__": 8 | # module being called directly, use absolute path 9 | from twitter import Boolean, Tweet, TweetType, TweetQueue 10 | from process_tweets import generate_tweets, search_next_tweet 11 | else: 12 | # module being called as package, use relative paths 13 | from .twitter import Boolean, Tweet, TweetType, TweetQueue 14 | from .process_tweets import generate_tweets, search_next_tweet 15 | 16 | # Helpful when testing locally 17 | from dotenv import load_dotenv 18 | 19 | load_dotenv() 20 | 21 | # Tweet Settings & Variables 22 | TWEET_TYPE = TweetType.THREAD 23 | 24 | # Directories 25 | CUR_DIR = os.path.dirname(os.path.abspath(__file__)) 26 | APP_DIR = os.path.abspath(os.path.join(CUR_DIR, os.pardir)) 27 | LOG_FILE = os.path.join(APP_DIR, "twitter-bot.log") 28 | TEXT_FILE = os.path.join(APP_DIR, "data/processed/quants_tweets.txt") 29 | 30 | # Load your Twitter API keys 31 | TWITTER_API_KEY = os.getenv("TWITTER_API_KEY") 32 | TWITTER_API_SECRET = os.getenv("TWITTER_API_SECRET") 33 | TWITTER_ACCESS_TOKEN = os.getenv("TWITTER_ACCESS_TOKEN") 34 | TWITTER_ACCESS_TOKEN_SECRET = os.getenv("TWITTER_ACCESS_TOKEN_SECRET") 35 | TWITTER_BEARER_TOKEN = os.getenv("TWITTER_BEARER_TOKEN") 36 | 37 | OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") 38 | 39 | 40 | # set up logging to file 41 | logging.basicConfig( 42 | level=logging.INFO, 43 | format="%(asctime)s %(name)-12s %(levelname)-8s %(message)s", 44 | datefmt="%y-%m-%d %H:%M", 45 | filename="twitter-bot.log", 46 | filemode="a", 47 | ) 48 | 49 | 50 | class TwitterBot: 51 | """TwitterBot class to help us organize our code and manage shared state""" 52 | 53 | def __init__(self): 54 | self.twitter_api = tweepy.Client( 55 | bearer_token=TWITTER_BEARER_TOKEN, 56 | consumer_key=TWITTER_API_KEY, 57 | consumer_secret=TWITTER_API_SECRET, 58 | access_token=TWITTER_ACCESS_TOKEN, 59 | access_token_secret=TWITTER_ACCESS_TOKEN_SECRET, 60 | wait_on_rate_limit=True, 61 | ) 62 | 63 | self.llm = ChatOpenAI( 64 | temperature=0.3, 65 | openai_api_key=OPENAI_API_KEY, 66 | model_name="gpt-3.5-turbo-0613", 67 | ) 68 | 69 | self.text_file = TEXT_FILE 70 | 71 | self.tweetQueue = TweetQueue.from_text_file(self.text_file) 72 | 73 | def verify_tweet_to_send(self) -> None: 74 | if len(self.tweetQueue.tweets_ready_for_sending) == 0: 75 | self.process_tweets() 76 | 77 | def process_tweets(self): 78 | generate_tweets(self.llm, self.tweetQueue) 79 | self.tweetQueue.to_text_file(self.text_file) 80 | 81 | def post_thread(self, tweet: Tweet) -> None: 82 | tweet_d = asdict(tweet) 83 | try: 84 | for key, tweet_thread in tweet_d.items(): 85 | if key == "Hook": 86 | _tweet_thread = self.twitter_api.create_tweet(text=tweet_thread) 87 | else: 88 | self.twitter_api.create_tweet( 89 | text=tweet_thread, 90 | in_reply_to_tweet_id=_last_tweet_id.data["id"], 91 | ) 92 | _last_tweet_id = _tweet_thread 93 | logging.info(f"Sent Status: TRUE. Tweet: {tweet_thread}") 94 | return True 95 | except Exception as e: 96 | logging.warning(e) 97 | return False 98 | 99 | def post_tweet(self, tweet: Tweet) -> None: 100 | quant_tweet = tweet.to_text() 101 | try: 102 | self.twitter_api.create_tweet(text=quant_tweet) 103 | logging.info(f"Sent Status: TRUE. Tweet: {quant_tweet}") 104 | return True 105 | except Exception as e: 106 | logging.warning(e) 107 | return False 108 | 109 | def save_file(self): 110 | self.tweetQueue.to_text_file(self.text_file) 111 | logging.info("Latest version of tweets saved down.") 112 | 113 | 114 | def run_quantpy_feed_bot(): 115 | """Run twitter bot, search for next tweet and send in thread""" 116 | # First step is to import file of topics and ides into TweetQueue 117 | twitterBot = TwitterBot() 118 | # ensure there are tweets to send 119 | twitterBot.verify_tweet_to_send() 120 | # Identify Tweet Track to Send 121 | quant_tweet_track = search_next_tweet(twitterBot.tweetQueue) 122 | # post single tweet 123 | if TWEET_TYPE == TweetType.SINGLE: 124 | if twitterBot.post_tweet(tweet=quant_tweet_track.tweet): 125 | quant_tweet_track.update_sent_status(Boolean.TRUE) 126 | # post tweet thread 127 | elif TWEET_TYPE == TweetType.THREAD: 128 | if twitterBot.post_thread(tweet=quant_tweet_track.tweet): 129 | quant_tweet_track.update_sent_status(Boolean.TRUE) 130 | # save down file 131 | twitterBot.save_file() 132 | 133 | 134 | if __name__ == "__main__": 135 | run_quantpy_feed_bot() 136 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==3.8.6 2 | aiosignal==1.3.1 3 | annotated-types==0.6.0 4 | anyio==3.7.1 5 | appnope==0.1.3 6 | APScheduler==3.10.4 7 | argon2-cffi==23.1.0 8 | argon2-cffi-bindings==21.2.0 9 | arrow==1.3.0 10 | asttokens==2.4.0 11 | async-lru==2.0.4 12 | async-timeout==4.0.3 13 | attrs==23.1.0 14 | Babel==2.13.0 15 | backcall==0.2.0 16 | beautifulsoup4==4.12.2 17 | bleach==6.1.0 18 | certifi==2023.7.22 19 | cffi==1.16.0 20 | charset-normalizer==3.3.0 21 | comm==0.1.4 22 | dataclasses-json==0.6.1 23 | debugpy==1.8.0 24 | decorator==5.1.1 25 | defusedxml==0.7.1 26 | executing==2.0.0 27 | fastjsonschema==2.18.1 28 | fqdn==1.5.1 29 | frozenlist==1.4.0 30 | idna==3.4 31 | ipykernel==6.25.2 32 | ipython==8.16.1 33 | ipython-genutils==0.2.0 34 | ipywidgets==8.1.1 35 | isoduration==20.11.0 36 | jedi==0.19.1 37 | Jinja2==3.1.2 38 | json5==0.9.14 39 | jsonpatch==1.33 40 | jsonpointer==2.4 41 | jsonschema==4.19.1 42 | jsonschema-specifications==2023.7.1 43 | jupyter==1.0.0 44 | jupyter-console==6.6.3 45 | jupyter-events==0.8.0 46 | jupyter-lsp==2.2.0 47 | jupyter_client==8.4.0 48 | jupyter_core==5.4.0 49 | jupyter_server==2.8.0 50 | jupyter_server_terminals==0.4.4 51 | jupyterlab==4.0.7 52 | jupyterlab-pygments==0.2.2 53 | jupyterlab-widgets==3.0.9 54 | jupyterlab_server==2.25.0 55 | langchain==0.0.319 56 | langsmith==0.0.47 57 | MarkupSafe==2.1.3 58 | marshmallow==3.20.1 59 | matplotlib-inline==0.1.6 60 | mistune==3.0.2 61 | multidict==6.0.4 62 | mypy-extensions==1.0.0 63 | nbclient==0.8.0 64 | nbconvert==7.9.2 65 | nbformat==5.9.2 66 | nest-asyncio==1.5.8 67 | notebook==7.0.6 68 | notebook_shim==0.2.3 69 | numpy==1.26.1 70 | oauthlib==3.2.2 71 | openai==0.28.1 72 | overrides==7.4.0 73 | packaging==23.2 74 | pandocfilters==1.5.0 75 | parso==0.8.3 76 | pexpect==4.8.0 77 | pickleshare==0.7.5 78 | platformdirs==3.11.0 79 | prometheus-client==0.17.1 80 | prompt-toolkit==3.0.39 81 | psutil==5.9.6 82 | ptyprocess==0.7.0 83 | pure-eval==0.2.2 84 | pycparser==2.21 85 | pydantic==2.4.2 86 | pydantic_core==2.10.1 87 | Pygments==2.16.1 88 | python-dateutil==2.8.2 89 | python-dotenv==1.0.0 90 | python-json-logger==2.0.7 91 | pytz==2023.3.post1 92 | PyYAML==6.0.1 93 | pyzmq==25.1.1 94 | qtconsole==5.4.4 95 | QtPy==2.4.0 96 | referencing==0.30.2 97 | requests==2.31.0 98 | requests-oauthlib==1.3.1 99 | rfc3339-validator==0.1.4 100 | rfc3986-validator==0.1.1 101 | rpds-py==0.10.6 102 | Send2Trash==1.8.2 103 | six==1.16.0 104 | sniffio==1.3.0 105 | soupsieve==2.5 106 | SQLAlchemy==2.0.22 107 | stack-data==0.6.3 108 | tenacity==8.2.3 109 | terminado==0.17.1 110 | tinycss2==1.2.1 111 | tornado==6.3.3 112 | tqdm==4.66.1 113 | traitlets==5.11.2 114 | tweepy==4.14.0 115 | types-python-dateutil==2.8.19.14 116 | typing-inspect==0.9.0 117 | typing_extensions==4.8.0 118 | tzlocal==5.2 119 | uri-template==1.3.0 120 | urllib3==2.0.7 121 | wcwidth==0.2.8 122 | webcolors==1.13 123 | webencodings==0.5.1 124 | websocket-client==1.6.4 125 | widgetsnbextension==4.0.9 126 | yarl==1.9.2 --------------------------------------------------------------------------------