nicknochnack / MLTradingBot

796 stars 325 forks source link

A couple Mods Not Exactly working that Im able to tell #20

Open QueRicoChulo opened 6 months ago

QueRicoChulo commented 6 months ago

I am new to this and coding. I made a couple mods to the file so I would like someone to review it and help me where it needs help please and please adapt if you think its a good idea....

your patience is appreciated

Danny

from lumibot.brokers import Alpaca from lumibot.backtesting import YahooDataBacktesting from lumibot.strategies.strategy import Strategy from lumibot.traders import Trader from datetime import datetime from alpaca_trade_api import REST from timedelta import Timedelta from finbert_utils import estimate_sentiment

import numpy as np #added to get pythons math functions

API_KEY = "YOUR API KEY" API_SECRET = "YOUR API SECRET" BASE_URL = "https://paper-api.alpaca.markets"

ALPACA_CREDS = { "API_KEY":API_KEY, "API_SECRET": API_SECRET, "PAPER": True }

class MLTrader(Strategy): def initialize(self, symbol:str="SPY", cash_at_risk:float=.5): self.symbol = symbol self.sleeptime = "24H" self.last_trade = None self.cash_at_risk = cash_at_risk self.api = REST(base_url=BASE_URL, key_id=API_KEY, secret_key=API_SECRET)

# def position_sizing(self): 
#     cash = self.get_cash() 
#     last_price = self.get_last_price(self.symbol)
#     quantity = round(cash * self.cash_at_risk / last_price,0)
#     return cash, last_price, quantity

def position_sizing(self):
    cash = self.get_cash()
    last_price = self.get_last_price(self.symbol)
    atr = self.calculate_atr(self.symbol)
    take_profit, stop_loss = self.set_take_profit_stop_loss(last_price, atr)
    quantity = round(cash * self.cash_at_risk / last_price, 0)
    return cash, last_price, quantity, take_profit, stop_loss

def calculate_atr(self, symbol, period=14):
    # Fetch historical data for ATR calculation, implement accordingly
    pass

def set_take_profit_stop_loss(self, last_price, atr, multiplier=2):
    take_profit = last_price + atr * multiplier
    stop_loss = last_price - atr * multiplier
    return take_profit, stop_loss

def get_dates(self): 
    today = self.get_datetime()
    three_days_prior = today - Timedelta(days=3)
    return today.strftime('%Y-%m-%d'), three_days_prior.strftime('%Y-%m-%d')

def get_sentiment(self): 
    today, three_days_prior = self.get_dates()
    news = self.api.get_news(symbol=self.symbol, 
                             start=three_days_prior, 
                             end=today) 
    news = [ev.__dict__["_raw"]["headline"] for ev in news]
    probability, sentiment = estimate_sentiment(news)
    return probability, sentiment 

def on_trading_iteration(self):
    cash, last_price, quantity = self.position_sizing() 
    probability, sentiment = self.get_sentiment()

    # if cash > last_price: 
    #     if sentiment == "positive" and probability > .999: 
    #         if self.last_trade == "sell": 
    #             self.sell_all() 
    #         order = self.create_order(
    #             self.symbol, 
    #             quantity, 
    #             "buy", 
    #             type="bracket", 
    #             take_profit_price=last_price*1.20, 
    #             stop_loss_price=last_price*.95
    #         )
    #         self.submit_order(order) 
    #         self.last_trade = "buy"
    #     elif sentiment == "negative" and probability > .999: 
    #         if self.last_trade == "buy": 
    #             self.sell_all() 
    #         order = self.create_order(
    #             self.symbol, 
    #             quantity, 
    #             "sell", 
    #             type="bracket", 
    #             take_profit_price=last_price*.8, 
    #             stop_loss_price=last_price*1.05
    #         )
    #         self.submit_order(order) 
    #         self.last_trade = "sell"

    if cash > last_price:
        if sentiment == "positive" and probability > .999:
            if self.last_trade == "sell":
                self.sell_all()
            order = self.create_order(
                self.symbol,
                quantity,
                "buy",
                type="bracket",
                take_profit_price=take_profit,
                stop_loss_price=stop_loss
            )
            self.submit_order(order)
            self.last_trade = "buy"
        elif sentiment == "negative" and probability > .999:
            if self.last_trade == "buy":
                self.sell_all()
            order = self.create_order(
                self.symbol,
                quantity,
                "sell",
                type="bracket",
                take_profit_price=take_profit,
                stop_loss_price=stop_loss
            )
            self.submit_order(order)
            self.last_trade = "sell"

start_date = datetime(2020,1,1) end_date = datetime(2023,12,31) broker = Alpaca(ALPACA_CREDS) strategy = MLTrader(name='mlstrat', broker=broker, parameters={"symbol":"SPY", "cash_at_risk":.5}) strategy.backtest( YahooDataBacktesting, start_date, end_date, parameters={"symbol":"SPY", "cash_at_risk":.5} )

trader = Trader()

trader.add_strategy(strategy)

trader.run_all()

winstonwilliamsiii commented 6 months ago

@QueRicoChulo I will be standing on the sidelines watching for the resolution as this is my first GitHub experience. May I ask, which algorithm from Lumibot are you coding for ticker SPY (good idea to automate that) then API your app to Alpaca to run with your broker... right?

winstonwilliamsiii commented 6 months ago

@QueRicoChulo Aye yo, I pasted and ran the code into Colab Notebook there were no errors....

QueRicoChulo commented 6 months ago

@QueRicoChulo Aye yo, I pasted and ran the code into Colab Notebook there were no errors....

well in the Testing of the original code that the writer coded. The amount of Paper money was decreasing and increasing during the test. I dont know how to as of yet read the logs too well, I am also wondering if there is a way to put more than one symbol to trade in the code, also about the sentiment part with the news. Does that have to be defined differently depending on what the symbol being traded is? Example if trading Harley Davidson. Would the news need to be defined differently?

winstonwilliamsiii commented 6 months ago

@QueRicoChulo That's a good question about changing market news on sentiment analysis give me a day to review. As for the first issue I am very new to Python though after just 2 hours and 40 pages of notes and a quick search on [StackOver Flow] we would have to add a FUNCTION into the script. Once defined, Python functions can be called multiple times and from any location in a program. Do you know how? I will try to write a script this afternoon...here is what I got so far.

For example

stocks = ('AAPL', 'GOOGL', 'YHOO', 'MSFT', 'AMZN', 'DAI')

winstonwilliamsiii commented 6 months ago

@QueRicoChulo Currently, the script is for SPY. Do we know what the source of the market data is ? It says Yahoo Back testing.... was not aware Yahoo offered Quant Fin/ML back testing. Lumibot gave the strategy but do we know which strategy?

QueRicoChulo commented 5 months ago

@QueRicoChulo Currently, the script is for SPY. Do we know what the source of the market data is ? It says Yahoo Back testing.... was not aware Yahoo offered Quant Fin/ML back testing. Lumibot gave the strategy but do we know which strategy?

strategy was one my friend who is a stock trader had suggested to me so I added it. The Code breaks down like this

  1. Imports and Setup: The script starts by importing necessary libraries and modules, setting up the API connection with Alpaca for trading and YahooDataBacktesting for data.

  2. Strategy Definition (MLTrader):

    • Initialization: Sets up initial parameters like the trading symbol (SPY), cash risk per trade (50% of available cash), and trading API credentials.
    • Position Sizing: Determines how many shares to buy or sell based on available cash, the last price of the stock, and a calculated Average True Range (ATR) for risk management.
    • ATR Calculation: A method placeholder to calculate ATR, which helps in setting dynamic take-profit and stop-loss levels based on market volatility.
    • Take-Profit and Stop-Loss: Computes take-profit and stop-loss prices using the ATR and a predefined multiplier.
    • Sentiment Analysis: Extracts recent news headlines for the specified symbol and evaluates their sentiment to decide the trading direction. The sentiment analysis likely uses a pre-trained model from 'finbert_utils'.
  3. Trading Logic (on_trading_iteration):

    • Cash and Price Check: Ensures there is enough cash to make a trade.
    • Sentiment and Probability Check: Trades only when the sentiment is strongly positive or negative (probability > 0.999).
    • Order Execution: Uses bracket orders for entering trades, which include specified take-profit and stop-loss levels. A bracket order ensures that the trade is exited either at a profit or a controlled loss.
    • State Management: Keeps track of the last trading action to avoid entering conflicting trades consecutively.
  4. Backtesting Setup:

    • Time Frame: Specifies the start and end dates for the backtesting period.
    • Strategy and Broker Configuration: Links the strategy with the broker setup and the backtesting engine.
    • Execution: Runs the backtesting to evaluate how the strategy would have performed over the specified period.
  5. Real-Time Trading Execution:

    • Trader Object: Prepares a trader object that manages the running of the strategy in either a backtesting or live environment.

This trading strategy utilizes a combination of technical indicators (ATR for risk management) and sentiment analysis (news impact) to make trading decisions. The use of bracket orders for trade management helps to automatically secure profits and limit losses, crucial for effective risk management in trading.

QueRicoChulo commented 5 months ago

@QueRicoChulo That's a good question about changing market news on sentiment analysis give me a day to review. As for the first issue I am very new to Python though after just 2 hours and 40 pages of notes and a quick search on [StackOver Flow] we would have to add a FUNCTION into the script. Once defined, Python functions can be called multiple times and from any location in a program. Do you know how? I will try to write a script this afternoon...here is what I got so far. #For example stocks = ('AAPL', 'GOOGL', 'YHOO', 'MSFT', 'AMZN', 'DAI')

symbol in place of STOCKS?