unter “Aktien für den Optionshandel finden” hatten wir erläutert, wie man mit finviz für den Optionshandel geeignete Aktien finden kann. Ein weitere Auswahlstrategie, die mit finviz nicht parametrierbar ist, bietet die folgende Vorgehensweise, die mit Algo-Trading realisiert werden kann (bitte beachte auch hier die Risikohinweise). Wir suchen hierzu Aktien, die folgende Bedingungen erfüllen:
- wir suchen Aktien aus dem S&P500, die mindestens historische Kurse über 3 Jahre vorweisen
- die gesuchten Aktien sollen im aktuellen Monat, in den zurückliegenden 5 Jahren möglichst keinen negativen Trend aufweisen
- der maximale Kursrückgang im betrachteten Monat sollte einen definierten Prozentwert nicht überschreiten
- das aktuelle Optionskontrakt Handelsvolumen sollte hoch sein
- als konkretere Ziele können wir z.B. ergänzen: mindestens 80% positiver Trend in den letzten Jahren, Kursrückgang nicht unter -5%, Kursanstieg > 10%, Handelsvolumen > 1000 Kontrakte
Die Strategie ist es hierbei, die Aktien zu finden, die gemäß ihrem historischen Trend die o.g. Anforderungen erfüllen, mit der Hoffnung, dass diese auch in diesem Jahr ein ähnlich positives Verhalten aufzeigen. Mittels eines Bull Put Spread oder Bull Call Spread können dann verlustbegrenzt zu diesen Aktien Optionen gehandelt werden. Idealerweise sollte die Option in der letzten Woche des Vormonats erworben werden.
Als Grundlage zum Thema Python Programmierung der Verweis auf unseren Einführungsbeitrag zu diesem Thema.
Der folgende Python Code ermittelt uns die notwendigen Daten. Die Funktion getData() übernimmt hierbei die Datenermittlung. Sie prüft zunächst ob bereits eine gespeicherte Auswertung vorliegt, bzw. wiederholt diese, wenn die letzte Auswertung mehr als 330 Tage zurück liegt.
Die Funktion get_sp500_tickers() bestimmt die aktuellen Ticker-Symbole des S&P500. Im weiteren Ablauf werden dann über die Funktion check_stock_performance() die Performance-Werte (Erfolgsrate %, Max. Verlust %, Max. Gewinn %, mittlere Rendite %) und über check_option_volume() das aktuelle Options Kontraktvolumen bestimmt. Final wird das Ergebnis in einer CSV-Tabelle gespeichert, d.h. eine weitere Auswertung mit Excel wäre ebenfalls möglich.
import os
import yfinance as yf
import logging
import pandas as pd
from datetime import date, datetime, timedelta
# Liste der Aktien, die analysiert werden sollen
database = 'stockPerformance.csv'
df = pd.DataFrame()
# Funktion zum Abrufen der S&P 500 Liste
def get_sp500_tickers():
url = 'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies'
table = pd.read_html(url)
df = table[0]
return df['Symbol'].tolist()
# Bestimmung der Performance Werte
def check_stock_performance(ticker):
# 5 Jahre Kursdaten von yahoo einlsesen
years = 5
try:
stock = yf.Ticker(ticker)
data = stock.history(period=str(years)+"y", interval="1d")
except:
return None
if data.empty:
return None
end_date = datetime.today()
start_date = end_date - timedelta(days=years*365) # 5 Jahre zurück
results = {}
# Performancedaten pro Monat bestimmen
for mo in range(1,13):
positive_years = 0
total_years = years
max_loss = None
max_win = None
mwin = 0
# jeder zurückliegende Jahr betrachten
for year in range(years):
year_data = data[(data.index.month == mo) & (data.index.year == (end_date.year - 1 - year))]
if year_data.empty:
total_years -= 1
continue
# Verluste und Gewinne bestimmen
start_price = year_data.iloc[0]['Open']
end_price = year_data.iloc[-1]['Close']
min_price = year_data['Low'].min()
max_price = year_data['High'].max()
if (end_price > start_price):
positive_years += 1
loss = (min_price - start_price) / start_price
win = (max_price - start_price) / start_price
mwin += (end_price - start_price) / start_price
if max_loss == None or loss < max_loss:
max_loss = loss
if max_win == None or win > max_win:
max_win = win
if total_years < 3: # Mindestens 3 Jahre müssen Daten vorhanden sein
continue
# das Ergebnis ablegen
perfValue = (positive_years / total_years)
results[mo] = (max_loss,max_win,mwin/total_years,perfValue)
return results
# Bestimmung des Options Handelsvolumens
def check_option_volume(ticker):
try:
stock = yf.Ticker(ticker)
options = stock.options
# aktuellen Kontrakt bestimmen
if len(options) > 0:
option_chain = stock.option_chain(options[0])
else:
return None
except:
return None
if not options:
return None
# Volumen des aktuellsten Kontrakts
total_volume = option_chain.calls['volume'].sum() + option_chain.puts['volume'].sum()
return total_volume
def getData():
global database,df
# wenn nicht älter als 330 Tage csv einlesen
if os.path.exists(database):
c_time = os.path.getmtime(database)
dt = datetime.fromtimestamp(c_time).date()
agedays = int((date.today()-dt) / timedelta(days=1))
if agedays < 330:
df = pd.read_csv(database)
return
# Datenaktualisierung starten
sp500_tickers = get_sp500_tickers()
# yf trace deaktivieren
logger = logging.getLogger('yfinance')
logger.disabled = True
logger.propagate = False
# performance Daten bestimmen
data=[]
stockdata = {}
for stock in sp500_tickers:
results = check_stock_performance(stock)
if results == None:
continue
vol = check_option_volume(stock)
print(stock)
for mo in range(1,13):
if mo in results:
(maxloss,maxwin,mwin,perfValue) = results[mo]
stockdata["Aktie"] = stock
stockdata["Erfolgsrate %"] = round(perfValue * 100.0,2)
stockdata["Max. Verlust %"] = round(maxloss * 100.0,2)
stockdata["Max. Gewinn %"] = round(maxwin * 100.0,2)
stockdata["Mtl. Rendite %"] = round(mwin * 100.0,2)
stockdata["Volumen"] = vol
stockdata["Monat"] = mo
data.append({**stockdata})
# Speicherung in CSV Datei
df = pd.DataFrame(data).sort_values(by=['Monat','Erfolgsrate %','Max. Verlust %','Volumen'], ascending=False)
df.to_csv(database, index=False)
# Ausgabe der Top Aktien
def getBestofMonth(month):
global df
dfm = df[df['Monat'] == month]
print(dfm.head())
# main
getData()
month = datetime.now().month
getBestofMonth(month)
getBestofMonth(month%12+1)
Die Funktion getBestofMonth() liefert uns die Top 5 Aktien für den aktuellen und den nächsten Monat, sortiert nach Erfolgsrate und Max. Verlust.
Gemäß dieser Auswertung können wir nun entscheiden, ob wir auf Grund des möglichen max. Verlust eher kein Risiko eingehen wollen, d.h. nicht handeln, oder welche Strikelevel wir für eine Option setzen möchten. Als Zieltermin für die Laufzeit der Optionen sollten wir das Monatsende wählen.
Als Options-Strategie eignen sich der Bull Call Spreads für Positionen, für die eine Kursteigerung wahrscheinlich ist. Spreads sind insofern attraktiv, da sie ein begrenztes Verlustrisiko aufweisen, aber der Bull Call Spread ist nicht geeignet, wenn sich der Kurs nur seitwärts oder abwärts bewegen sollte. Als Zielkurs für den Strikepreis von Call Kauf und Verkauf könnte man den “max. Kursverlust %” wählen. Zum Beispiel bei einem aktuellen Kurs 100$ und -5% max. Kursverlust, dann Call Verkauf zum Basispreis 105$ und Call Kauf zum Basispreis 95$. Der max. Verlust ergibt sich aus Prämie Call Verkauf – Prämie Call Kauf, wenn beide Optionen verfallen, d.h. der Aktienkurs unter den unteren (Long Call) Strikepreis fällt. Eine Gewinnmitnahme ist denkbar, wenn die Aktien-Kurssteigerung die mittlere Kurssteigerung und der Kurs den oberen Strikepreis überschritten hat.
Als weitere Options-Strategie der Bull Put Spread für Positionen, für die eine Kursteigerung oder Seitwärtsbewegung wahrscheinlich ist. Verkauf einer Put-Option mit höherem Strike-Preis (im Beispiel oben 105$) und Kauf einer Put-Option mit niedrigerem Strike-Preis (im Beispiel oben 95$). Der max. Verlust ergibt sich aus Prämie Put Verkauf – Strikepreis-Differenz * 100 (im Beispiel ist die Strikepreis-Differenz 10$).
Hier nun eine Auswertung auf Basis des oben gezeigten Python Codes:
Favorisierte Aktien für den Monat März
Aktie | Erfolgsrate % | Max. Verlust % | Max. Gewinn % | Mtl. Rendite % | Volumen | Monat |
---|---|---|---|---|---|---|
KR | 100.0 | -3.9 | 30.05 | 13.5 | 20573.0 | 3 |
CEG | 100.0 | -4.01 | 29.5 | 13.36 | 3645.0 | 3 |
WMT | 100.0 | -5.2 | 19.03 | 5.48 | 24139.0 | 3 |
CARR | 100.0 | -5.68 | 43.75 | 13.47 | 395.0 | 3 |
GILD | 100.0 | -7.55 | 23.39 | 4.05 | 1103.0 | 3 |