Skip to content

Commit

Permalink
V2.1.5 (#25)
Browse files Browse the repository at this point in the history
* update version

* removed vscode

* removed fluff

* update py-alpaca-api
  • Loading branch information
TexasCoding authored Jun 16, 2024
1 parent 83d3035 commit 1a24541
Show file tree
Hide file tree
Showing 15 changed files with 574 additions and 261 deletions.
54 changes: 17 additions & 37 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "py-alpaca-daily-losers"
version = "2.1.4"
version = "2.1.5"
description = "Daily Losers strategy, uses py-alpaca-api for Alpaca Markets integration."
authors = ["TexasCoding <jeff10278@me.com>"]
license = "MIT"
Expand All @@ -18,7 +18,6 @@ openai = "^1.30.5"
slack-sdk = "^3.27.2"
ta = "^0.11.0"
python-dotenv = "^1.0.1"
rich = "^13.7.1"


[tool.poetry.group.dev.dependencies]
Expand Down
24 changes: 1 addition & 23 deletions src/alpaca_daily_losers/close_positions.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,13 @@
import logging

from py_alpaca_api import Stock, Trading
from rich.console import Console
from rich.progress import (
BarColumn,
MofNCompleteColumn,
Progress,
TextColumn,
TimeElapsedColumn,
TimeRemainingColumn,
)

from alpaca_daily_losers.global_functions import (
get_ticker_data,
send_message,
send_position_messages,
)

# Define custom progress bar
progress_bar = Progress(
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
BarColumn(),
MofNCompleteColumn(),
TextColumn("•"),
TimeElapsedColumn(),
TextColumn("•"),
TimeRemainingColumn(),
)

console = Console()


class ClosePositions:
def __init__(self, trading_client: Trading, stock_client: Stock, py_logger: logging.Logger):
Expand All @@ -56,7 +34,7 @@ def sell_positions_from_criteria(self) -> None:
Exception: If an error occurs while selling the positions.
"""

console.print("Selling positions based on criteria...", style="bold green")
# console.print("Selling positions based on criteria...", style="bold green")
try:
stocks_to_sell = self.get_stocks_to_sell()
if not stocks_to_sell:
Expand Down
121 changes: 36 additions & 85 deletions src/alpaca_daily_losers/daily_losers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@
import pandas as pd
from dotenv import load_dotenv
from py_alpaca_api import PyAlpacaAPI
from rich.console import Console
from rich.progress import (
BarColumn,
MofNCompleteColumn,
Progress,
TextColumn,
TimeElapsedColumn,
TimeRemainingColumn,
)

from alpaca_daily_losers.close_positions import ClosePositions
from alpaca_daily_losers.global_functions import (
Expand All @@ -24,22 +15,6 @@
from alpaca_daily_losers.openai import OpenAIAPI
from alpaca_daily_losers.statistics import Statistics

# from tqdm import tqdm


# Define custom progress bar
progress_bar = Progress(
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
BarColumn(),
MofNCompleteColumn(),
TextColumn("•"),
TimeElapsedColumn(),
TextColumn("•"),
TimeRemainingColumn(),
)

console = Console()

# get a custom logger & set the logging level
py_logger = logging.getLogger(__name__)
logging.basicConfig(
Expand Down Expand Up @@ -107,11 +82,7 @@ def check_for_buy_opportunities(self) -> None:
tickers = self.filter_tickers_with_news(losers)

if len(tickers) > 0:
console.print(
f"Found [bold]{len(tickers)}[/bold] buy \
opportunities based on daily losers and news sentiment",
style="red",
)
print(f"Found [bold]{len(tickers)}[/bold] buy opportunities.")
self.open_positions(tickers=tickers)
else:
print("No buy opportunities found")
Expand All @@ -131,15 +102,6 @@ def open_positions(self, tickers: list, ticker_limit: int = 8) -> None:
Returns:
None
"""
# print(
# "Buying orders based on buy opportunities and openai sentiment. \
# Limit to 8 stocks by default"
# )
console.print(
f"Entering new posistions based on criteria\n.\
Limit to {ticker_limit} stocks.",
style="green",
)

available_cash = self.alpaca.trading.account.get().cash

Expand Down Expand Up @@ -210,37 +172,32 @@ def filter_tickers_with_news(self, tickers) -> list:
openai = OpenAIAPI()
filtered_tickers = []

with progress_bar as progress:
console.print(
f"\nAnalyzing news for [bold]{len(tickers)}[/bold] symbols, using OpenAI: ",
style="yellow",
)
for i, ticker in progress.track(enumerate(tickers), total=len(tickers)):
try:
articles = self.alpaca.trading.news.get_news(symbol=ticker)
except Exception as e:
py_logger.warning(f"Error getting articles for {ticker}. Error {e}")
continue

if articles is None:
continue

if len(articles) > 0:
bullish = 0
bearish = 0
for art in articles[:3]:
sentiment = openai.get_sentiment_analysis(
title=art["title"],
symbol=art["symbol"],
article=art["content"],
)
if sentiment == "BULLISH":
bullish += 1
else:
bearish += 1

if bullish > bearish:
filtered_tickers.append(ticker)
for i, ticker in enumerate(tickers):
try:
articles = self.alpaca.trading.news.get_news(symbol=ticker)
except Exception as e:
py_logger.warning(f"Error getting articles for {ticker}. Error {e}")
continue

if articles is None:
continue

if len(articles) > 0:
bullish = 0
bearish = 0
for art in articles[:3]:
sentiment = openai.get_sentiment_analysis(
title=art["title"],
symbol=art["symbol"],
article=art["content"],
)
if sentiment == "BULLISH":
bullish += 1
else:
bearish += 1

if bullish > bearish:
filtered_tickers.append(ticker)

if len(filtered_tickers) == 0:
print("No tickers with news found")
Expand Down Expand Up @@ -272,21 +229,15 @@ def get_daily_losers(self) -> list:
send_message("No daily losers found.")
return []

with progress_bar as progress:
console.print(
f"Getting recommendations for [bold]{len(losers)}[/bold] symbols, \
from Yahoo Finance: ",
style="green",
)
for i, ticker in progress.track(enumerate(losers), total=len(losers)):
try:
sentiment = self.alpaca.trading.recommendations.get_sentiment(ticker)
except Exception as e:
py_logger.warning(f"Error getting sentiment from Yahoo. Error: {e}")
sentiment = "NEUTRAL"
for i, ticker in enumerate(losers):
try:
sentiment = self.alpaca.trading.recommendations.get_sentiment(ticker)
except Exception as e:
py_logger.warning(f"Error getting sentiment from Yahoo. Error: {e}")
sentiment = "NEUTRAL"

if sentiment == "NEUTRAL" or sentiment == "BEARISH":
losers.remove(ticker)
if sentiment == "NEUTRAL" or sentiment == "BEARISH":
losers.remove(ticker)

self.update_or_create_watchlist(name="DailyLosers", symbols=losers)

Expand Down Expand Up @@ -342,7 +293,7 @@ def buy_criteria(self, data: pd.DataFrame) -> list:
filtered_data = list(buy_filtered_data["symbol"])

if len(filtered_data) == 0:
console.print("No tickers meet the buy criteria", style="red")
print("No tickers meet the buy criteria")
return []

self.update_or_create_watchlist(name="DailyLosers", symbols=filtered_data)
Expand Down
Loading

0 comments on commit 1a24541

Please sign in to comment.