Full Code of mtamer/python-rsi for AI

master 406e9f5223ea cached
7 files
15.2 KB
4.4k tokens
7 symbols
1 requests
Download .txt
Repository: mtamer/python-rsi
Branch: master
Commit: 406e9f5223ea
Files: 7
Total size: 15.2 KB

Directory structure:
gitextract_1_kn1di5/

├── .gitignore
├── .vscode/
│   └── settings.json
├── README.md
└── src/
    ├── main.py
    ├── requirements.txt
    ├── stock.py
    └── stocks.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Taken from https://github.com/github/gitignore/blob/master/Python.gitignore

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

================================================
FILE: .vscode/settings.json
================================================
{
    "python.pythonPath": "/usr/bin/python3"
}

================================================
FILE: README.md
================================================
# python-rsi

RSI (Relative Strength Index) written in Python

![Python RSI Image](https://github.com/mtamer/python-rsi/blob/master/src/images/example.png)

## About

Relative Strength Index written in Python. The whole point of this application is to be able to come up with a list of as many different types of stocks (stock tickers) that you want to screen and see if it meets the Relative Strength criteria. A combination of the RSI and the 20 and 200 day Moving Average (MA) tend to be strong and popular indicators to determine the future behavior of a stock.

At the end of pulling stock data, a table is shown displaying metrics of the stocks pulled along with a link to view the chart.

![Stock Data Table](https://github.com/mtamer/python-rsi/blob/master/src/images/pulled-data-table.png)

## To Install

1. Clone repo: `git clone https://github.com/mtamer/python-rsi.git`
2. `cd src`
3. `pip install -r requirements.txt`
4. Look inside the `main.py` file and put all the stocks you want to monitor in there or inside of `stocks.txt`
5. To run: `python main.py`
6. Enjoy!

## Disclaimer

This repository is only for educational purposes. The owner and contributors of this repository are not responsible for how you use this code and the gains/losses you accumulate.


================================================
FILE: src/main.py
================================================
#!/usr/bin/env python3

import datetime
import random
import time
from urllib.request import urlopen

import matplotlib
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import numpy as np
import pandas_datareader.data as web
import pylab
from mplfinance.original_flavor import candlestick_ohlc
from pandas.core.common import flatten
from tabulate import tabulate

from stock import Stock

matplotlib.rcParams.update({'font.size': 9})

stocks = []

# If stocks array is empty, pull stock list from stocks.txt file
stocks = stocks if len(stocks) > 0 else [
    line.rstrip() for line in open("stocks.txt", "r")]

# Time frame you want to pull data from
start = datetime.datetime.now()-datetime.timedelta(days=365)
end = datetime.datetime.now()

if __name__ == "__main__":

    # Array of moving averages you want to get
    MAarr = [20, 200]

    allData = []

    for ticker in stocks:

        try:
            data = []

            print("Pulling data for " + ticker)

            stock = Stock(ticker, start, end)

            # Append data to array
            data.append(ticker.upper())

            data.append(stock.closes[-1])

            for MA in MAarr:
                computedSMA = stock.SMA(period=MA)
                # print(computedSMA)
                data.append(computedSMA[-1])

            currentRsi = float("{:.2f}".format(stock.rsi[-1]))

            if currentRsi > 70:
                data.append(str(currentRsi) + " 🔥")
            elif currentRsi < 30:
                data.append(str(currentRsi) + " 🧊")
            else:
                data.append(currentRsi)

            chartLink = "https://finance.yahoo.com/quote/" + ticker + "/chart?p=" + ticker

            data.append(chartLink)

            allData.append(data)

            # Shows chart only if current RSI is greater than or less than 70 or 30 respectively
            if currentRsi < 30 or currentRsi > 70:

                stock.graph(MAarr)

        except Exception as e:
            print('Error: ', str(e))

    print(tabulate(allData, headers=flatten([
        'Stock', 'Price', [str(x) + " MA" for x in MAarr], "RSI", "chart"])))


================================================
FILE: src/requirements.txt
================================================
astroid==2.4.2
autopep8==1.5.3
certifi==2020.4.5.2
chardet==3.0.4
colorama==0.4.3
cycler==0.10.0
idna==2.9
isort==4.3.21
kiwisolver==1.2.0
lazy-object-proxy==1.4.3
lxml==4.5.1
matplotlib==3.2.2
mccabe==0.6.1
mplfinance==0.12.5a3
numpy==1.18.5
pandas==1.0.5
pandas-datareader==0.8.1
pycodestyle==2.6.0
pylint==2.5.3
pyparsing==2.4.7
python-dateutil==2.8.1
pytz==2020.1
requests==2.24.0
six==1.15.0
tabulate==0.8.7 
toml==0.10.1
typed-ast==1.4.1
urllib3==1.25.9
wrapt==1.12.1


================================================
FILE: src/stock.py
================================================
#!/usr/bin/env python3

import datetime
import random
from urllib.request import urlopen

import matplotlib
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
import numpy as np
import pandas_datareader.data as web
import pylab
from mplfinance.original_flavor import candlestick_ohlc

matplotlib.rcParams.update({'font.size': 9})


class Stock:

    ticker = None
    dates = None
    closes = None
    highs = None
    lows = None
    opens = None
    volumes = None
    rsi = None

    def __init__(self, ticker, start, end=datetime.datetime.now()):
        self.ticker = ticker

        """
        Different sources for pulling data can be found here:
        https://readthedocs.org/projects/pandas-datareader/downloads/pdf/latest/
        """

        stockData = web.DataReader(ticker, 'yahoo', start, end)

        self.dates = [mdates.date2num(d) for d in stockData.index]
        self.closes = stockData['Close']
        self.highs = stockData['High']
        self.lows = stockData['Low']
        self.opens = stockData['Open']
        self.volumes = stockData['Volume']

        self.rsi = self.RSI(self.closes)

    def RSI(self, prices, n=14):
        deltas = np.diff(prices)
        seed = deltas[:n+1]
        up = seed[seed >= 0].sum()/n
        down = -seed[seed < 0].sum()/n
        rs = up/down
        rsi = np.zeros_like(prices)
        rsi[:n] = 100. - 100./(1.+rs)

        for i in range(n, len(prices)):
            delta = deltas[i-1]  # The diff is 1 shorter

            if delta > 0:
                upval = delta
                downval = 0.
            else:
                upval = 0.
                downval = -delta

            up = (up*(n-1) + upval)/n
            down = (down*(n-1) + downval)/n

            rs = up/down
            rsi[i] = 100. - 100./(1.+rs)

        return rsi

    def SMA(self, period, values=None):

        values = self.closes if values is None else values

        """
        Simple Moving Average. Periods are the time frame. For example, a period of 50 would be a 50 day
        moving average. Values are usually the stock closes but can be passed any values
        """

        weigths = np.repeat(1.0, period)/period
        smas = np.convolve(values, weigths, 'valid')
        return smas  # as a numpy array

    def EMA(self, period, values=None):

        values = self.closes if values is None else values

        """
        Exponential Moving Average. Periods are the time frame. For example, a period of 50 would be a 50 day
        moving average. Values are usually the stock closes but can be passed any values
        """

        weights = np.exp(np.linspace(-1., 0., period))
        weights /= weights.sum()
        a = np.convolve(values, weights, mode='full')[:len(values)]
        a[:period] = a[period]
        return a

    def MACD(self, x, slow=26, fast=12):
        """
        Compute the MACD (Moving Average Convergence/Divergence) using a fast and slow exponential moving avg'
        return value is emaslow, emafast, macd which are len(x) arrays
        """

        emaslow = self.EMA(slow, x)
        emafast = self.EMA(fast, x)
        return emaslow, emafast, emafast - emaslow

    def graph(self, movingAverageArr=[]):
        try:

            x = 0
            y = len(self.dates)
            newAr = []
            while x < y:
                appendLine = self.dates[x], self.opens[x], self.closes[x], self.highs[x], self.lows[x], self.volumes[x]
                newAr.append(appendLine)
                x += 1

            # Fix this
            SP = len(self.dates[200-1:])

            fig = plt.figure(facecolor='#07000d')

            ax1 = plt.subplot2grid(
                (6, 4), (1, 0), rowspan=4, colspan=4, facecolor='#07000d')
            candlestick_ohlc(ax1, newAr[-SP:], width=.6,
                             colorup='#53c156', colordown='#ff1717')

            for MA in movingAverageArr:

                computedSMA = self.SMA(MA, self.closes)

                # Used to generate random hex color to put on graph
                def r(): return random.randint(0, 255)
                randomColor = '#%02X%02X%02X' % (r(), r(), r())

                maLabel = str(MA) + ' SMA'
                ax1.plot(self.dates[-SP:], computedSMA[-SP:], randomColor,
                         label=maLabel, linewidth=1.5)

            ax1.grid(False, color='w')
            ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
            ax1.xaxis.set_major_formatter(
                mdates.DateFormatter('%Y-%m-%d'))
            ax1.yaxis.label.set_color("w")
            ax1.spines['bottom'].set_color("#5998ff")
            ax1.spines['top'].set_color("#5998ff")
            ax1.spines['left'].set_color("#5998ff")
            ax1.spines['right'].set_color("#5998ff")
            ax1.tick_params(axis='y', colors='w')
            plt.gca().yaxis.set_major_locator(mticker.MaxNLocator(prune='upper'))
            ax1.tick_params(axis='x', colors='w')
            plt.ylabel('Stock price and Volume')

            maLeg = plt.legend(loc=9, ncol=2, prop={'size': 7},
                               fancybox=True, borderaxespad=0.)
            maLeg.get_frame().set_alpha(0.4)
            textEd = pylab.gca().get_legend().get_texts()
            pylab.setp(textEd[0:5], color='w')

            volumeMin = 0

            ax0 = plt.subplot2grid(
                (6, 4), (0, 0), sharex=ax1, rowspan=1, colspan=4, facecolor='#07000d')

            rsiCol = '#c1f9f7'
            posCol = '#386d13'
            negCol = '#8f2020'

            ax0.plot(self.dates[-SP:], self.rsi[-SP:],
                     rsiCol, linewidth=1.5)
            ax0.axhline(70, color=negCol)
            ax0.axhline(30, color=posCol)
            ax0.fill_between(self.dates[-SP:], self.rsi[-SP:], 70, where=(self.rsi[-SP:]
                                                                          >= 70), facecolor=negCol, edgecolor=negCol, alpha=0.5)
            ax0.fill_between(self.dates[-SP:], self.rsi[-SP:], 30, where=(self.rsi[-SP:]
                                                                          <= 30), facecolor=posCol, edgecolor=posCol, alpha=0.5)
            ax0.set_yticks([30, 70])
            ax0.yaxis.label.set_color("w")
            ax0.spines['bottom'].set_color("#5998ff")
            ax0.spines['top'].set_color("#5998ff")
            ax0.spines['left'].set_color("#5998ff")
            ax0.spines['right'].set_color("#5998ff")
            ax0.tick_params(axis='y', colors='w')
            ax0.tick_params(axis='x', colors='w')
            plt.ylabel('RSI')

            ax1v = ax1.twinx()
            ax1v.fill_between(self.dates[-SP:], volumeMin,
                              self.volumes[-SP:], facecolor='#00ffe8', alpha=.4)
            ax1v.axes.yaxis.set_ticklabels([])
            ax1v.grid(False)

            # Edit this to 3, so it's a bit larger
            ax1v.set_ylim(0, 3*self.volumes.max())
            ax1v.spines['bottom'].set_color("#5998ff")
            ax1v.spines['top'].set_color("#5998ff")
            ax1v.spines['left'].set_color("#5998ff")
            ax1v.spines['right'].set_color("#5998ff")
            ax1v.tick_params(axis='x', colors='w')
            ax1v.tick_params(axis='y', colors='w')
            ax2 = plt.subplot2grid(
                (6, 4), (5, 0), sharex=ax1, rowspan=1, colspan=4, facecolor='#07000d')
            fillcolor = '#00ffe8'
            nslow = 26
            nfast = 12
            nema = 9
            emaslow, emafast, macd = self.MACD(self.closes)
            ema9 = self.EMA(nema, macd)
            ax2.plot(self.dates[-SP:], macd[-SP:],
                     color='#4ee6fd', lw=2)
            ax2.plot(self.dates[-SP:], ema9[-SP:],
                     color='#e1edf9', lw=1)
            ax2.fill_between(self.dates[-SP:], macd[-SP:]-ema9[-SP:], 0,
                             alpha=0.5, facecolor=fillcolor, edgecolor=fillcolor)

            plt.gca().yaxis.set_major_locator(mticker.MaxNLocator(prune='upper'))
            ax2.spines['bottom'].set_color("#5998ff")
            ax2.spines['top'].set_color("#5998ff")
            ax2.spines['left'].set_color("#5998ff")
            ax2.spines['right'].set_color("#5998ff")
            ax2.tick_params(axis='x', colors='w')
            ax2.tick_params(axis='y', colors='w')
            plt.ylabel('MACD', color='w')
            ax2.yaxis.set_major_locator(
                mticker.MaxNLocator(nbins=5, prune='upper'))
            for label in ax2.xaxis.get_ticklabels():
                label.set_rotation(45)

            plt.suptitle(self.ticker.upper(), color='w')

            plt.setp(ax0.get_xticklabels(), visible=False)
            plt.setp(ax1.get_xticklabels(), visible=False)

            # ax1.annotate('Look Here!', (date[-1], Av1[-1]),
            #              xytext=(0.8, 0.9), textcoords='axes fraction',
            #              arrowprops=dict(facecolor='white', shrink=0.05),
            #              fontsize=14, color='w',
            #              horizontalalignment='right', verticalalignment='bottom')

            plt.subplots_adjust(left=.09, bottom=.14,
                                right=.94, top=.95, wspace=.20, hspace=0)

            plt.show()
            fig.savefig('example.png', facecolor=fig.get_facecolor())

        except Exception as e:
            print('Error graphing data: ', str(e))


================================================
FILE: src/stocks.txt
================================================
baba
roku
msft
amzn
tqqq
nvda
vgt
twtr
dis
t
snap
tsla
Download .txt
gitextract_1_kn1di5/

├── .gitignore
├── .vscode/
│   └── settings.json
├── README.md
└── src/
    ├── main.py
    ├── requirements.txt
    ├── stock.py
    └── stocks.txt
Download .txt
SYMBOL INDEX (7 symbols across 1 files)

FILE: src/stock.py
  class Stock (line 19) | class Stock:
    method __init__ (line 30) | def __init__(self, ticker, start, end=datetime.datetime.now()):
    method RSI (line 49) | def RSI(self, prices, n=14):
    method SMA (line 76) | def SMA(self, period, values=None):
    method EMA (line 89) | def EMA(self, period, values=None):
    method MACD (line 104) | def MACD(self, x, slow=26, fast=12):
    method graph (line 114) | def graph(self, movingAverageArr=[]):
Condensed preview — 7 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (17K chars).
[
  {
    "path": ".gitignore",
    "chars": 2113,
    "preview": "# Taken from https://github.com/github/gitignore/blob/master/Python.gitignore\n\n# Byte-compiled / optimized / DLL files\n_"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 47,
    "preview": "{\n    \"python.pythonPath\": \"/usr/bin/python3\"\n}"
  },
  {
    "path": "README.md",
    "chars": 1277,
    "preview": "# python-rsi\n\nRSI (Relative Strength Index) written in Python\n\n![Python RSI Image](https://github.com/mtamer/python-rsi/"
  },
  {
    "path": "src/main.py",
    "chars": 2186,
    "preview": "#!/usr/bin/env python3\n\nimport datetime\nimport random\nimport time\nfrom urllib.request import urlopen\n\nimport matplotlib\n"
  },
  {
    "path": "src/requirements.txt",
    "chars": 474,
    "preview": "astroid==2.4.2\nautopep8==1.5.3\ncertifi==2020.4.5.2\nchardet==3.0.4\ncolorama==0.4.3\ncycler==0.10.0\nidna==2.9\nisort==4.3.21"
  },
  {
    "path": "src/stock.py",
    "chars": 9431,
    "preview": "#!/usr/bin/env python3\n\nimport datetime\nimport random\nfrom urllib.request import urlopen\n\nimport matplotlib\nimport matpl"
  },
  {
    "path": "src/stocks.txt",
    "chars": 54,
    "preview": "baba\nroku\nmsft\namzn\ntqqq\nnvda\nvgt\ntwtr\ndis\nt\nsnap\ntsla"
  }
]

About this extraction

This page contains the full source code of the mtamer/python-rsi GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 7 files (15.2 KB), approximately 4.4k tokens, and a symbol index with 7 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!