-
Notifications
You must be signed in to change notification settings - Fork 16
test #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
test #14
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Auto detect text files and perform LF normalization | ||
| * text=auto |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| config.py | ||
| # 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 | ||
|
|
||
| # poetry | ||
| # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. | ||
| # This is especially recommended for binary packages to ensure reproducibility, and is more | ||
| # commonly ignored for libraries. | ||
| # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control | ||
| #poetry.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/ | ||
|
|
||
| # PyCharm | ||
| # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can | ||
| # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore | ||
| # and can be added to the global gitignore or merged into this file. For a more nuclear | ||
| # option (not recommended) you can uncomment the following to ignore the entire idea folder. | ||
| #.idea/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| import requests | ||
| import config | ||
| from datetime import date, timedelta | ||
|
|
||
|
|
||
| # --------- GENERAL ----------- | ||
| # IFTTT Webhooks credentials, for now | ||
| event_name = "" | ||
|
|
||
| # Calculate the start and end dates in YYYY-MM-DD format for the 7-day period, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. character limit for comments is 72 |
||
| # with end_date being yesterday and start_date being 7 days ago. | ||
| today = date.today() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe put the finding of start dates and end dates in a function, that would increase clarity |
||
| end_date = today - timedelta(days=1) | ||
| start_date = end_date - timedelta(days=6) | ||
|
|
||
| # --------- 7 DAY AVERAGE ----------- | ||
| # Function to get the stock data from the last 7 days and return JSON response | ||
| def get_previous_7_days(api, start_date, today): | ||
| tickers = ["TSLA", "AAPL", "MSFT", "GOOG", "NKE"] | ||
| response = {} | ||
| for ticker in tickers: | ||
| url = f"https://api.twelvedata.com/time_series?symbol={ticker}&interval=1day&start_date={start_date}&end_date={today}&apikey={api}" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. character limit for code is 79 |
||
| response[ticker] = requests.get(url).json() | ||
| return response | ||
|
|
||
| # Calculate the 7-day average price for each ticker | ||
| data_7_days = get_previous_7_days(config.api_key1, start_date, today) | ||
|
|
||
| for ticker, stock_data in data_7_days.items(): | ||
| closing_prices = [float(day['close']) for day in stock_data['values']] | ||
| average = sum(closing_prices) / len(closing_prices) | ||
| print(f"{ticker} Average Closing Price: {average:.2f}") | ||
|
|
||
|
|
||
| # --------- REAL-TIME PRICE ----------- | ||
| # Function to retrieve real-time price | ||
| def get_realtime_price(api): | ||
| tickers = ["TSLA", "AAPL", "MSFT", "GOOG", "NKE"] | ||
| response = {} | ||
| for ticker in tickers: | ||
| url = f"https://api.twelvedata.com/price?symbol={ticker}&apikey={api}" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can add error handling when making API requests, I didn't do that for my code either, but its worth looking into |
||
| response[ticker] = requests.get(url).json() | ||
| return response | ||
|
|
||
| # Store real-time price data | ||
| data_realtime = get_realtime_price(config.api_key2) | ||
|
|
||
|
|
||
| # --------- MARKET OPEN PRICE ----------- | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very good comment structure |
||
| # Function to get the market open, to compare real-time price to | ||
| def get_market_open(api, today): | ||
| tickers = ["TSLA", "AAPL", "MSFT", "GOOG", "NKE"] | ||
| response = {} | ||
| for ticker in tickers: | ||
| url = f"https://api.twelvedata.com/time_series?symbol={ticker}&interval=1day&outputsize=1&apikey={api}" | ||
| response[ticker] = requests.get(url).json() | ||
| return response | ||
|
|
||
| # Store market open price data | ||
| data_marketopen = get_market_open(config.api_key3, today) | ||
|
|
||
| # print for visualisation purposes: | ||
| for ticker, stock_data in data_marketopen.items(): | ||
| open_prices = [float(day['open']) for day in stock_data['values']] | ||
| print(f"{ticker} Market Open: {open_prices}") | ||
|
|
||
| # --------- TRIGGER WEBHOOK IF CONDITION IS MET ----------- | ||
| # Function to trigger IFTTT event | ||
| def trigger(event_name): | ||
| url = f'https://maker.ifttt.com/trigger/{event_name}/with/key/{config.ifttt_key}' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You have your secret keys in a config file, which is good practice, something I wish I'd done. |
||
| response = requests.post(url) | ||
| if response.status_code == 200: | ||
| print(f"Triggered the IFTTT applet for {event_name} successfully.") | ||
| else: | ||
| print(f"Failed to trigger the IFTTT applet for {event_name}.") | ||
|
|
||
| # Map of tickers to event names | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using dictionaries to map the stock names to their event names is such a smart idea, really centralises all event handling. Wish I'd though of that. |
||
| ticker_to_event = { | ||
| "TSLA": "TSLA_Price_Drop", | ||
| "AAPL": "AAPL_Price_Drop", | ||
| "MSFT": "MSFT_Price_Drop", | ||
| "GOOG": "GOOG_Price_Drop", | ||
| "NKE": "NKE_Price_Drop" | ||
| } | ||
|
|
||
| # Converting £0.25 to USD with current exchange rate | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a valid and smart idea for currency conversion, simply converting £0.25 to USD, and going through all the conditionals in dollars. Although, converting all the API data from USD to GBP would be better for the client, as you can then send them stock data in GBP through IFTTT. |
||
| # and assigning it a variable to calculate the variance between real time and market open | ||
| def currency_conversion(api): | ||
| response = {} | ||
| url = f"https://api.twelvedata.com/currency_conversion?symbol=GBP/USD&amount=0.25&apikey={api}" | ||
| response = requests.get(url).json() | ||
| return response | ||
|
|
||
| pence_to_cents = currency_conversion(config.api_key1) | ||
| pence_to_cents = pence_to_cents['amount'] | ||
| print(f"Current USD value of £0.25: {pence_to_cents:.2f}") | ||
|
|
||
| # Check conditions and trigger the corresponding event | ||
| for ticker, stock_data in data_realtime.items(): | ||
| current_price = float(stock_data['price']) | ||
| event_name = ticker_to_event.get(ticker) | ||
| market_open_price = float(data_marketopen[ticker]['values'][0]['open']) | ||
| print(f"{ticker} Current Price: {current_price:.2f}") | ||
|
|
||
| if current_price <= market_open_price - pence_to_cents: | ||
| trigger(event_name) | ||
| elif current_price < average: | ||
| trigger(event_name) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need an if name == main block at the end. Any code inside this block is what gets executed whenever you run this file in the terminal There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also you could've written some tests. For example, to check:
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general your code is very well organised and clear to read, with the way you've added comments at the start of each block and separated them out