candlestick2_ohlc > Lösung für x-Achse?

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

So, ich erläutere kurz das, was ich bisher programmiert habe:

Mit

Code: Alles auswählen

candlestick2_ohlc(ax, df['Open'], df['High'], df['Low'], df['Close'], width=0.4, colorup='k', colordown='r', alpha=0.75)
zeige ich den Candlestick-Chart eines DataFrames an.

Im Index - hier benannt mit 'Date' - liegt das Datum als String in der Form 'YYYYMMDD'. Hier wandle ich den Index als normale Spalte und den String in das DateTime-Format:

Code: Alles auswählen

df.index.rename('Date', inplace=True)
df.reset_index(inplace=True)
df['Date'] = pd.to_datetime(df['Date'].astype(str), format='%Y%m%d')
Nun habe ich Schwierigkeiten, dieses Datum in der Achse anzuzeigen, am liebsten im Format '18. Nov 2017'.
Mit den set_major_locator, set_major_formatter und ticker habe ich alle möglichen Beispiele über Google gefunden und getestet, aber ich komme damit nicht weiter.
Weshalb kann ich nicht einfach mit einer Funktion die Serie df['Date'] an ax übergeben?

Könnte mir jemand mit dem fehlenden Code und einer kleinen Erläuterung weiterhelfen?
Oder ein passender Link?

Vielen Dank und ein schönes Wochenende!
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Benutzeravatar
pixewakb
User
Beiträge: 1405
Registriert: Sonntag 24. April 2011, 19:43

Schaust du mal, ob du damit etwas anfangen kannst:

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os

from matplotlib.finance import candlestick_ohlc
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.dates import num2date, date2num
import matplotlib.dates


def create_SimpleChart(title,
                       quotes,
                       filename,
                       path = "."):
    fig, ax = plt.subplots(num=None, figsize=(14, 10), dpi=80, facecolor='w', edgecolor='k')
    candlestick_ohlc(ax, quotes, width=1.2, colorup='g', colordown='r')
    plt.title(title)
    ax.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%Y-%m-%d'))
    ax.grid(color='0.75', linestyle='-', linewidth=1)
    ax.legend(loc='upper left', bbox_to_anchor=(0., 1.))
    ax.set_xlabel("Datum")
    ax.set_ylim(0)
    fig.autofmt_xdate()
    fig.tight_layout()
    plt.savefig('{}'.format(os.path.join(path, filename)))
    plt.close('all')

    
def __test_create_SimpleChart():

    dates     = [732797.0, 732828.0, 732858.0, 732889.0, 732920.0, 732950.0, 732981.0, 733011.0, 733042.0, 733073.0]
    prices_o = [60.0, 61.0, 62.0, 61.0, 62.0,  63.0, 64.0, 65.0, 66.0, 68.0]
    prices_h = [64.0, 63.0, 64.0, 65.0, 66.0,  66.0, 64.0, 65.0, 66.0, 69.0]
    prices_l = [60.0, 60.0, 62.0, 60.0, 61.0,  63.0, 64.0, 63.0, 64.0, 65.0]
    prices_c = [64.0, 64.0, 62.0, 60.0, 62.0,  64.0, 64.0, 63.0, 64.0, 67.0]
    
    quotes = [tuple([dates[i],
                     prices_o[i],
                     prices_h[i],
                     prices_l[i],
                     prices_c[i]]) for i in range(len(dates))]

    create_SimpleChart("Titel",
                       quotes,
                       "__Test.png")

if __name__ == "__main__":

    __test_create_SimpleChart()

Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

Dein Code ist wunderbar, weil: Er funktioniert!
Damit konnte ich einige Verständnisprobleme und Fehlerquellen ausräumen.

Nun hakt es "nur noch" am Format der Datum-Index-Spalte. Ich lese meine Daten über meinen Account bei Interactive Brokers über die IB-API ein und erhalte hiermit das Datum als str in der Form 20171124, also %Y%m%d.

Ich habe nun rausgefunden, dass ...
... ich zunächst das Datetime-Format benötige, welches ich durch "strptime(datum_als_string, "%Y%m%d")" erhalten müsste, und ...
... dieses dann für candlestick2_ohlc in den quotes als "time must be in float days format - see date2num" haben müsste.

Leider funktioniert dies nicht mit

Code: Alles auswählen

from time import strptime
from matplotlib.dates import date2num
...
benoetigtes_date_format = date2num(strptime(datum_als_string, "%Y%m%d"))
Nach
20171124
erhalte ich
time.struct_time(tm_year=2017, tm_mon=11, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=328, tm_isdst=-1)
bzw.
(2017, 11, 24, 0, 0, 0, 4, 328, 1)

Doch dann erscheint ein Fehler-Gewirr, endend mit

Code: Alles auswählen

File "/usr/local/lib/python3.6/site-packages/matplotlib/dates.py", line 222, in _to_ordinalf
    base = float(dt.toordinal())
AttributeError: 'numpy.int64' object has no attribute 'toordinal'
Es wäre großartig, wenn ihr mir bei dieser Formatwandlung noch helfen könntet. Danke!
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

Hier wird es sogar so gelöst:

Code: Alles auswählen

float_days = date2num(datetime.datetime.strptime(date_string, '%Y%m%d%H%M%S%f'))
(https://stackoverflow.com/questions/341 ... matplotlib)

... wieso es dann bei mir nicht klappt ...
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Benutzeravatar
pixewakb
User
Beiträge: 1405
Registriert: Sonntag 24. April 2011, 19:43

Das ist aber genauso, wie ich das jetzt auch gelöst hätte! Du bastelst Dir da kein datetime-Objekt, sondern ein time-Objekt, daran würde ich mal arbeiten und ich würde schauen, ob die Umwandlung klappt. Es sieht so als, als würdest du mit einem String weiterarbeiten.

Code: Alles auswählen

import datetime
from matplotlib.dates import date2num

date_string = "20171124"

date = datetime.date(int(date_string[:4]),
                     int(date_string[4:6]),
                     int(date_string[-2:]))

print(date)

print(date2num(date))
Normalerweise würde ich datetime.datetime.strptime() nutzen, was aber gerade auch bei mir nicht funktionierte. Obige Lösung kannst du in eine Funktion packen und z. B. die Umwandlung in einer list comprehension machen.
Benutzeravatar
pixewakb
User
Beiträge: 1405
Registriert: Sonntag 24. April 2011, 19:43

Ich war mal bei einem Meetup, wo es um Investment-Banking ging. Die haben einen Algorithmus geschrieben, der Investment-Entscheidungen getroffen hat, allerdings hing das Ding bei denen nicht an der API eines Brokers, sondern hat Entscheidungen ausgegeben, die dann von den Leuten geprüft und falls OK, dann an eine Bank weitergegeben haben. Ich wäre vorsichtig deren API zu nutzen und ein Tool selbsttätig Entscheidungen treffen zu lassen - ein kleiner Programmierfehler an der falschen Stelle könnte dich in kürzester Zeit ruinieren :oops:

Meine Meinung.
Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

pixewakb hat geschrieben:[...]Normalerweise würde ich datetime.datetime.strptime() nutzen, was aber gerade auch bei mir nicht funktionierte. Obige Lösung kannst du in eine Funktion packen und z. B. die Umwandlung in einer list comprehension machen.
Danke dir. Habe es erst einzeln getestet. Erfolgreich. Im Code eingebaut. Erfolgreich.
Aaaaaber: Die Anzeige - der Chart - ist nun verschoben.

Jetzt sehen meine Basisdaten (V2.0) so aus:

Code: Alles auswählen

          Open    High     Low   Close     Volume
736653  114.00  115.00  113.65  114.80  1421089.0
736654  114.55  115.45  113.70  114.40  1725893.0
736655  114.35  114.75  113.20  113.25  1781315.0
736656  112.90  114.60  112.50  113.85  1404341.0
736657  114.05  115.35  113.35  114.20  1223795.0
<class 'pandas.core.frame.DataFrame'>
Aber der Chart hat x-Achsen-Probleme. Ohne die Datumswandlung sieht alles gut aus - ausser der x-Achse -, also mit Basis (V1.0):

Code: Alles auswählen

            Open    High     Low   Close     Volume
20171120  114.00  115.00  113.65  114.80  1421089.0
20171121  114.55  115.45  113.70  114.40  1725893.0
20171122  114.35  114.75  113.20  113.25  1781315.0
20171123  112.90  114.60  112.50  113.85  1404341.0
20171124  114.05  115.35  113.35  114.20  1223795.0
<class 'pandas.core.frame.DataFrame'>
Also bei V1.0 stehen an der x-Achse alle Daten wie in der Index-Zeile diagonal und nebeneinander. Bei V2.0 stehen nur ganz links und ganz rechts scheinbar viele Daten "übereinander". Auf dem Rest der Achse nichts. Ebenso sieht auch der Plot aus.

Woran kann das liegen?

Habe übrigens auch versucht, einfach statt "20171124" den Datums-Index in einen String mit "24.11.2017" zu wandeln. Da sortiert er auch automatisch erst nach Tagen (01.01., 01.02., ...), weshalb die Anzeige auch falsch ist.
Somit wäre eine Überlegung, ob man den funktionierenden Chart aus V1.0 nimmt und nur die Sortierung für "d.m.Y" irgendwie übermittelt, so dass die Reihenfolge "richtig" bleibt. Geht das irgendwie?

Vielen Dank!
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

pixewakb hat geschrieben:Ich war mal bei einem Meetup, wo es um Investment-Banking ging. Die haben einen Algorithmus geschrieben, der Investment-Entscheidungen getroffen hat, allerdings hing das Ding bei denen nicht an der API eines Brokers, sondern hat Entscheidungen ausgegeben, die dann von den Leuten geprüft und falls OK, dann an eine Bank weitergegeben haben. Ich wäre vorsichtig deren API zu nutzen und ein Tool selbsttätig Entscheidungen treffen zu lassen - ein kleiner Programmierfehler an der falschen Stelle könnte dich in kürzester Zeit ruinieren :oops:

Meine Meinung.
Ich nutze auch vorerst "nur" die Realtime-Daten, um mit diesen bisher manuelle (Taschenrechner+Excel) Abläufe und Berechnungen zu automatisieren und Zeit zu sparen und diese aktuellen Kalkulationen ständig über einen Server auch mobil zur Verfügung zu haben, um - wie du schreibst - selbst Entscheidungen zu treffen.
Algo-Trading oder Robo-Trading werde ich sicher mal mit einem Paper-Account testen, aber das habe ich aktuell nicht vor, real umzusetzen.

Danke dennoch für den Hinweis!
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Benutzeravatar
pixewakb
User
Beiträge: 1405
Registriert: Sonntag 24. April 2011, 19:43

PythonTrader hat geschrieben:Also bei V1.0 stehen an der x-Achse alle Daten wie in der Index-Zeile diagonal und nebeneinander. Bei V2.0 stehen nur ganz links und ganz rechts scheinbar viele Daten "übereinander". Auf dem Rest der Achse nichts. Ebenso sieht auch der Plot aus.

Woran kann das liegen?
Mir ist nicht klar, welches Problem sich ergibt. Wenn Version 1 läuft, warum nutzt du es dann nicht? Ich kenne kein Beispiel, wo pandas genutzt wurde. Ich kenne nur den work around mit der Übergabe von tuple-Werten. Anzeigeprobleme bei matplolib, das liegt m. E. daran, dass du es noch nicht optimal eingestellt hast. Bei matplotlib sollte sich m. E. alles einstellen lassen, allerdings bin ich da nicht firm. Sorry. :K
Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

pixewakb hat geschrieben:
PythonTrader hat geschrieben:Also bei V1.0 stehen an der x-Achse alle Daten wie in der Index-Zeile diagonal und nebeneinander. Bei V2.0 stehen nur ganz links und ganz rechts scheinbar viele Daten "übereinander". Auf dem Rest der Achse nichts. Ebenso sieht auch der Plot aus.

Woran kann das liegen?
Mir ist nicht klar, welches Problem sich ergibt. Wenn Version 1 läuft, warum nutzt du es dann nicht? Ich kenne kein Beispiel, wo pandas genutzt wurde. Ich kenne nur den work around mit der Übergabe von tuple-Werten. Anzeigeprobleme bei matplolib, das liegt m. E. daran, dass du es noch nicht optimal eingestellt hast. Bei matplotlib sollte sich m. E. alles einstellen lassen, allerdings bin ich da nicht firm. Sorry. :K
Okay, danke. Ich bin ja sehr froh, dass ich eine Version habe, die funktioniert. Das werde ich auch irgendwie hinbekommen. Wie gesagt, dein Beispiel hat sehr geholfen!
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Benutzeravatar
pixewakb
User
Beiträge: 1405
Registriert: Sonntag 24. April 2011, 19:43

Ich habe noch zwei Anmerkungen:

(1) Wenn Du mit so etwas Probleme hast, dann mach einen Screenshot, nutze einen der vielen Filehoster und verlinke den Bildschirm-Ausschnitt. Bei matplotlib (= mpl) ist es einfacher, weil du direkt das gespeicherte Bild nehmen könntest. Denke daran, dass du persönliche Daten (usw. usf.) herausnimmst.

(2) Manche Fragen sind m. E. sehr speziell. In diesem Forum scheint es wenige zu geben, die sich mit den Feinheiten von mpl auskennen. Du solltest ggf. mal bei stackoverflow vorbeischauen. Viele Sachen werden dort bereits beantwortet, zu Sachen, die dort bislang nicht abgedeckt werden, kannst du eine neue Frage stellen. Ich bin mir sehr sicher, dass es dort Leute gibt, die sich mit pandas und deiner Wunsch-Diagramm-Funktion auskennen.

Ich bin leider kein mpl-Experte...
evev
User
Beiträge: 27
Registriert: Dienstag 4. April 2017, 12:50

Hi,
ich wollte keinen neuen Thread öffnen, da ich eine ähnliche Frage habe bezüglich ohlc charts. Gibt es eine Möglichkeit die Candlestickbreite individuell anzupassen? Bsp wäre ein Volumecandle Chart.

candlestick2_ohlc(ax, df['Close'], width=0.4, colorup='k', colordown='r', alpha=0.75)

Würde gerne das width variabel gestalten nur funktioniert das nicht ganz. Habe es mit ner for schleife probiert, aber das klappt nicht.
Hat jemand von euch vielleicht eine Idee?

mfg

Sorry für die Nutzung des Threads :)
Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

evev hat geschrieben:Gibt es eine Möglichkeit die Candlestickbreite individuell anzupassen? Bsp wäre ein Volumecandle Chart.
Würde gerne das width variabel gestalten nur funktioniert das nicht ganz. Habe es mit ner for schleife probiert, aber das klappt nicht.
Hat jemand von euch vielleicht eine Idee?
Kein Problem, gerne.

Aber was hast du genau vor? Du willst die einzelnen Candlesticks unterschiedlich breit darstellen?
Das geht meiner Meinung nach sicher nicht, weil du der Funktion nur eine Width mitteilen kannst. Du müsstest - wo ich auch fast gelandet wäre - doch eine eigene Funktion schreiben bzw. die Ansätze im Internet-Dschungel für dich zusammensetzen.

Oder habe ich es falsch verstanden?
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Benutzeravatar
PythonTrader
User
Beiträge: 55
Registriert: Montag 13. Februar 2017, 22:31

pixewakb hat geschrieben:Ich habe noch zwei Anmerkungen:
(1) Wenn Du mit so etwas Probleme hast, dann mach einen Screenshot, nutze einen der vielen Filehoster und verlinke den Bildschirm-Ausschnitt. Bei matplotlib (= mpl) ist es einfacher, weil du direkt das gespeicherte Bild nehmen könntest. Denke daran, dass du persönliche Daten (usw. usf.) herausnimmst.
Daran hatte ich auch nicht gedacht, aber wie du unten schreibst, sind hier wohl kaum Programmierer mit Finanz-Hintergrund.
pixewakb hat geschrieben:(2) Manche Fragen sind m. E. sehr speziell. In diesem Forum scheint es wenige zu geben, die sich mit den Feinheiten von mpl auskennen. Du solltest ggf. mal bei stackoverflow vorbeischauen. Viele Sachen werden dort bereits beantwortet, zu Sachen, die dort bislang nicht abgedeckt werden, kannst du eine neue Frage stellen. Ich bin mir sehr sicher, dass es dort Leute gibt, die sich mit pandas und deiner Wunsch-Diagramm-Funktion auskennen.

Ich bin leider kein mpl-Experte...
Sympathisch, dass du das schreibst. "stackoverflow" kenne ich durch die vielen Suchen nach Python-Code-Fragen. Da landet man automatisch dort. Mal sehen, ob ich dort schreibe ... danke dir!
Nach Basic, Pascal, Visual Basic, C++, Visual C, HTML und PHP folgt endlich Python und Shell!
Antworten