89 lines
3.3 KiB
Python
89 lines
3.3 KiB
Python
import os
|
|
import time
|
|
import pandas as pd
|
|
import pandas_ta as ta
|
|
from dotenv import load_dotenv
|
|
from datetime import datetime, timedelta, timezone
|
|
from colorama import Fore, Style, init
|
|
|
|
from alpaca.trading.client import TradingClient
|
|
from alpaca.trading.requests import MarketOrderRequest, StopLossRequest, TakeProfitRequest
|
|
from alpaca.trading.enums import OrderSide, TimeInForce, OrderClass
|
|
from alpaca.data.historical import StockHistoricalDataClient
|
|
from alpaca.data.requests import StockBarsRequest
|
|
from alpaca.data.timeframe import TimeFrame
|
|
|
|
init(autoreset=True)
|
|
load_dotenv()
|
|
|
|
# --- PARAMETER ---
|
|
SYMBOL = "AAPL"
|
|
QTY_PER_TRADE = 10 # Anzahl der Aktien
|
|
RSI_LOWER = 30
|
|
RSI_UPPER = 70
|
|
STOP_LOSS_PCT = 0.05 # 5% Stop Loss
|
|
TAKE_PROFIT_PCT = 0.10 # 10% Take Profit (Optionales Ziel)
|
|
|
|
# Clients
|
|
trading_client = TradingClient(os.getenv('ALPACA_API_KEY'), os.getenv('ALPACA_SECRET_KEY'), paper=True)
|
|
data_client = StockHistoricalDataClient(os.getenv('ALPACA_API_KEY'), os.getenv('ALPACA_SECRET_KEY'))
|
|
|
|
def get_rsi():
|
|
try:
|
|
start_time = datetime.now(timezone.utc) - timedelta(days=50)
|
|
bars = data_client.get_stock_bars(StockBarsRequest(symbol_or_symbols=[SYMBOL], timeframe=TimeFrame.Hour, start=start_time))
|
|
df = bars.df.xs(SYMBOL)
|
|
rsi = ta.rsi(df['close'], length=14)
|
|
return rsi.iloc[-1], df['close'].iloc[-1]
|
|
except:
|
|
return None, None
|
|
|
|
def execute_trade(side, price):
|
|
"""Sendet eine automatisierte Order mit Stop-Loss an Alpaca"""
|
|
if side == "BUY":
|
|
# Berechnung der Stop-Loss und Take-Profit Preise
|
|
sl_price = price * (1 - STOP_LOSS_PCT)
|
|
tp_price = price * (1 + TAKE_PROFIT_PCT)
|
|
|
|
# Erstellung einer "Bracket Order" (Kauf + SL + TP gleichzeitig)
|
|
order_request = MarketOrderRequest(
|
|
symbol=SYMBOL,
|
|
qty=QTY_PER_TRADE,
|
|
side=OrderSide.BUY,
|
|
time_in_force=TimeInForce.GTC,
|
|
order_class=OrderClass.BRACKET, # Verbindet Kauf mit SL/TP
|
|
stop_loss=StopLossRequest(stop_price=round(sl_price, 2)),
|
|
take_profit=TakeProfitRequest(limit_price=round(tp_price, 2))
|
|
)
|
|
trading_client.submit_order(order_request)
|
|
print(f"{Fore.GREEN}>>> AUTOMATISCHER KAUF: {QTY_PER_TRADE} {SYMBOL} @ {price}$")
|
|
print(f"{Fore.YELLOW}>>> STOP-LOSS GESETZT BEI: {sl_price:.2f}$")
|
|
|
|
def main_loop():
|
|
print(f"{Fore.CYAN}=== BOT STARTET IM AUTOMATIK-MODUS (PAPER) ===")
|
|
while True:
|
|
rsi, price = get_rsi()
|
|
|
|
# Check ob bereits eine Position offen ist
|
|
try:
|
|
position = trading_client.get_open_position(SYMBOL)
|
|
has_position = True
|
|
except:
|
|
has_position = False
|
|
|
|
if rsi:
|
|
print(f"[{datetime.now().strftime('%H:%M:%S')}] {SYMBOL} Preis: {price}$ | RSI: {rsi:.2f}")
|
|
|
|
# KAUFEN: RSI zu niedrig & wir haben noch nichts gekauft
|
|
if rsi < RSI_LOWER and not has_position:
|
|
execute_trade("BUY", price)
|
|
|
|
# VERKAUFEN: RSI zu hoch & wir haben eine Position
|
|
elif rsi > RSI_UPPER and has_position:
|
|
trading_client.close_position(SYMBOL)
|
|
print(f"{Fore.RED}>>> AUTOMATISCHER VERKAUF (RSI TARGET ERREICHT)")
|
|
|
|
time.sleep(60)
|
|
|
|
if __name__ == "__main__":
|
|
main_loop() |