Data pro “devadesátku” zdarma a rychle

dataDneska se budu chlubit cizím peřím. Ale uvedu zdroje. Pod článkem o programování AOS v Pythonu (napsal Myk) se rozpoutala zajímavá diskuse. Díky čtenáři s přezdívkou VM jsme objevili zdroj burzovních dat IEX a díky komentáři čtenáře s přezdívkou “Balu” potom možnost, jak z tohoto zdroje “tahat” data více tickerů najednou. Ukázková spolupráce!

IEX jako zdroj dat

Člověk nemůže znát všechno a já to fakt neznal. IEX je tedy nejen burza, ale i poskytovatel dat. Dlužno říci, že poměrně přesných. API je triviální. Cena – free. Nutnost registrace – není. Redistribuce – ano, možná. jsou data realtime ? Ano. Jak často lze stahovat? No, víte co? Přečtěte si všechno tady.

Zdá se, že taková nabídka dat je příliš dobrá, než aby to byla pravda, nicméně po asi týdenním testování jsem na žádný vážnější zádrhel nenarazil.

Jak to funguje

Vhodně se zformátuje URL a přes https server vrátí odpověď ve formátu CSV nebo JSON. Oba jsou poměrně dost standardizovány, takže by s jejich zpracováním neměl být problém.

Protože není třeba API klíč, můžu rovnou uvést příklady. Ale neudělám to, to bych pouze opisoval dokumentaci, takže odkážu sem.

Balu

Čtenář Balu navrhl, že dávkové stažení více historických dat – tedy více tickerů najednou – by mělo jít přes něco jako

https://api.iextrading.com/1.0/stock/market/batch?symbols=aapl,fb,tsla&types=chart&range=1y

a víte co? Ten kluk šikovná měl naprostou pravdu. Čili teď už jen narvat do toho seznam tickerů a je vymalováno.

Jak na to prakticky

Použil jsem jako referenční implementaci PHP, kdyžtak to někdo může přepsat do Pythonu a vlepit do komentářů. Vypadá to celé nějak takto:

   1: <?

   2:   $tickery = array (

   3:   'AAPL','ABBV','ABT','ACN','AGN','AIG','ALL','AMGN','AMZN','AXP',

   4:   'BA','BAC','BIIB','BK','BLK','BMY','C','CAT','CELG','CL',

   5:   'CMCSA','COF','COP','COST','CSCO','CVS','CVX','DHR','DIS',

   6:   'DUK','EMR','EXC','F','FB','FDX','FOXA','GD','GE','GILD',

   7:   'GM','GOOG','GS','HAL','HD','HON','IBM','INTC','JNJ','JPM','KHC',

   8:   'KMI','KO','LLY','LMT','LOW','MA','MCD','MDLZ','MDT','MET',

   9:   'MMM','MO','MON','MRK','MS','MSFT','NEE','NKE','ORCL','OXY',

  10:   'PCLN','PEP','PFE','PG','PM','PYPL','QCOM','RTN','SBUX','SLB',

  11:   'SO','SPG','T','TGT','TWX','TXN','UNH','UNP','UPS','USB',

  12:   'UTX','V','VZ','WBA','WFC','WMT','XOM'

  13:   );

  14:

  15:   $url="https://api.iextrading.com/1.0/stock/market/batch?symbols=".

  16:   implode(',', $tickery).

  17:   "&types=chart&range=1y&filter=date,close";

  18:

  19:   $json = file_get_contents($url);   // roční historie

  20:   $vsechny_tickery = json_decode($json, true);   // asociativní pole

  21:

  22:   foreach ($vsechny_tickery as $nazev=>$ticker){

  23:

  24:     $ceny = array_column($ticker['chart'], 'close'); // zajímají nás ceny, ne datumy

  25:     $sma200 = trader_sma($ceny,200);

  26:     $sma5 = trader_sma($ceny,5);

  27:     $rsi2 = trader_rsi($ceny,2);

  28:

  29:     echo "Ticker: $nazev"."<BR>\n";

  30:     echo "Last: ".(end($ceny))."<BR>\n";

  31:     echo "SMA5: ".(end($sma5))."<BR>\n";

  32:     echo "SMA200: ".(end($sma200))."<BR>\n";

  33:     echo "RSI2: ".(end($rsi2))."<BR>\n";

  34:     echo "<BR>\n";

  35:

  36:   }

  37: ?>

 

Pro neznalé programování nebo neznalé PHP si dovolím krátké vysvětlení:

  • Řádky 2-13 jsou nuda, pouze definujeme seznam akcií. Použil jsem svůj seznam, možná máte trochu jiný.
  • Řádky 15-17 sestavují URL odkazu, z něhož budeme data čerpat. Tickery se vloží jako řetězec, kde položky budou oddělené čárkou (to dělá to implode).
  • Řádek 19 stahuje vlastní data ve formátu JSOU a ukládá do proměnné
  • Řádek 20 z toho dělá pole, které se pak bude procházet (to je ta smyčka na řádcích 22 – 36)
  • Pak už snad jen je zajímavý řádek 24, kde z pole obsahujícího dvojice údajů “datum” a “cena” taháme jen ty ceny – datumy nás nezajímají, víme, že to je seřazené vzestupně a končí to včerejškem, resp. posledním obchodním dnem.
  • Řádky 25-27 počítají průměry a RSI, k tomu se ještě dostanu,
  • A konečně řádky 29-34 pouze vypisují výsledky – název, cenu, průměry a RSI pro každý z tickerů.

A teď ještě poznámky a postřehy

Tak především rychlost – i na pomalejší lince je celý skript hotový za cca 2-3 vteřiny. On totiž kontaktuje server pouze jednou a data všech tickerů mají dohromady méně než 1 MB, takže se to zpracuje velmi rychle.

Dále k rozsahu stahovaných dat. část URL ve smyslu “range=1y” znamená, že stáhneme přesně rok dat. To činí myslím cca 252 obchodních dnů. My potřebujeme pro výpočet SMA200 minimálně 200 obchodních dnů, takže skript jich stahuje vždy cca o 50 dnů více. myslím, že to moc nevadí. Pokud by někdo věděl, jak omezit stahování přesně na 200 obchodních dnů, tak šup s tím do diskuse.

Poslední poznámka – zde uvedený skript řeší pouze historická data, jinými slovy výpočty indikátoru končí “včera”. Pokud by někdo chtěl použít skript a data z něj jako podklad pro aktuální rozhodování, tak to fungovat nebude, protože mu budou chybět údaje o ceně a indikátorech za aktuální den. Bude-li zájem, skript o aktuální den doplníme.

A teď to slavné RSI2

Já jsem se chtěl vyhnout stopadesátkrát omílanému dotazu “jak se počítá RSI”, takže jsem nad tím trochu přemýšlel. A objevil jsem, že PHP má nyní možnost použít knihovnu, která to udělá za Vás. Tím pádem by se tyhle opakující se dotazy nemusely v diskusi objevit. Nebo by se nemusely objevit tolikrát.

Knihovna se jmenuje prostě “trader” a není to nic jiného, než obal nad ještě mnohem známější knihovnou ta-lib. Čili kdo ji má v PHP naistalovánu, může počítat indikátory z datových řad, aniž by musel vědět, jak přesně výpočet funguje. Lze počítat desítky indikátorů průměry počínaje a třeba Ultimate Oscilátorem konče. Dobré vědět.

Příspěvek byl publikován v rubrice Nezařazené. Můžete si uložit jeho odkaz mezi své oblíbené záložky.

21 komentářů u Data pro “devadesátku” zdarma a rychle

  1. Lukas napsal:

    Tiez som nahradil yahoo za iextrading pred asi mesiacom (digrin.com) a tie updaty vyzeraju v pohode. Sem tam je tam HTTPError, ale malo. Mne akurat robi problem, ze z yahoo som tahal aj kanadske akcie napriklad, co myslim iextrading nema :(

  2. myk napsal:

    Kdo chce tahat data z iextrading.com v Pythonu, tak tady je hotová knihovna i s návodem. Data vrací rovnou v pandas dataframe:
    https://github.com/himoacs/iex_data
    dokumentace:
    http://www.enlistq.com/python-api-getting-market-financial-data-iex/

    Stačí si zkopírovat celou class API do programu svého programu a pak stahovat

    SP100symbols = [AAPL‘,’ABBV‘,’ABT‘,’ACN‘,’AGN‘,’AIG‘,’ALL‘, …….]
    api = API()

    čtení historických dat:
    histdata = api.get_trade_bars_data( SP100symbols, bucket = ‚1y‘)

    čtení live market dat (všechny symboly najednou):
    mktdata = api.get_latest_quote_and_trade( SP100symbols)

    čtení earnings (historie):
    earnings = api.get_earnings(SP100symbols)

    • admin napsal:

      Bacha ale na to, že „api.get_trade_bars_data“ podle https://github.com/himoacs/iex_data/blob/master/iex_data.py dělá fakt smyčku, čili to budou ty dvě minuty. Za dvě vteřiny to uděláš pouze použitím toho endpointu stock/market/batch?…

      • myk napsal:

        Máš pravdu, on to bere symbol po symbolu. Zkusím to přepsat.

        • Balu napsal:

          Už jsem se angažoval :)
          Pište si ty jednoduché funkce raději sami. Aspoň víte, co to přesně dělá.

          import io
          import requests
          import pandas as pd
          import json

          def get_EOD_prices_history(symbols):
          payload = {
          „symbols“: symbols,
          „format“: „json“,
          „types“: „chart“,
          „range“: „1y“,
          „filter“: „date,close“
          }
          endpoint = „stock/market/batch“

          raw = requests.get(base + endpoint, params=payload)
          raw = io.BytesIO(raw.content)
          prices_json = json.load(raw)
          prices_df = pd.DataFrame()
          for symbol in prices_json:
          df2 = pd.DataFrame(prices_json[symbol][‚chart‘])
          df2.insert(0,’Ticker_ID‘, symbol)
          prices_df = prices_df.append(df2)
          return prices_df

          • Myk napsal:

            Díky, to se bude hodit.
            Nicméně ke psaní vlastních funkcí – ne každej je profík a já než bych se učil jak zracovávat json, tak to radši obšlehnu, poslepuju několik knihoven a ušetřím čas. Když se ukáže, že je někde něco lepšího, tak nemám problém to nahradit.

            • admin napsal:

              Ona je pravda vlastně obojí. Obšlehnutím cizího kódu řešíme efektivně to, že znovu nevynalézáme kolo, na druhou stranu kdo se s vlastním kódem podělí, tak může pomoct ostatním.

              Tudíž díky oběma / všem v téhle diskusi!

              • Balu napsal:

                Já to nemyslel nijak ofenzivně, jen mám averzi k používání cizího kódu, který jsem si důkladně nezanalyzoval.
                Ono pak se mnohdy časově vyplatí napsat kus vlastního kódu, i vykopírovanáho z cizího kódu, než studovat celou importovanou knihovnu.
                A samozřejmě jak nás učili na škole, nejefektivnější metoda programování je copy&paste :)

                V tom mém kódu mi chybí jedna definice před tou fukcí, ať je to kompletní:
                base = „https://api.iextrading.com/1.0/“

  3. myk napsal:

    A RSI v pythonu:

    def RSI(df, column=“Close“, period=2):
    # wilder’s RSI

    delta = df[column].diff()
    up, down = delta.copy(), delta.copy()

    up[up 0] = 0

    rUp = up.ewm(com=period – 1, adjust=False).mean()
    rDown = down.ewm(com=period – 1, adjust=False).mean().abs()

    rsi = 100 – 100 / (1 + rUp / rDown)

    return rsi

    tuhle funkci pak stačí zavolat přes dataframe, který se načetl z csv nebo který se načetl z IEXTRADING a do kter0ho jsme si přidali nakonec dnešní ask cenu. Tohle volání do dataframe přidá sloupec s názvem ‚RSI2‘:
    histdata[‚RSI2‘] = RSI(data, column=DATA_COL, period=2)

    • myk napsal:

      DATA_COL je název sloupce, třeba ‚Close‘ nebo ‚Adj. Close‘

      • admin napsal:

        Zkoušel někdo použít https://github.com/mrjbq7/ta-lib? Jen se ptám, pythonu nerozumím, ale mohlo by to být vcelku komfortní řešení, ne?

        • myk napsal:

          Nezkoušel jsem, ale může se hodit. Jestli jsem to správně pochopil, ty funkce vrací numpy ndarrays, to znamená, že je to pole různých polí. ndarray moc neznám,, vím jen, že kdysi bylo ndarray nižší level, and kterým byl postavený pandas dataframe, ale pak se to rozešlo. Takže pandas dneska už je trochu něco jiného než ndarray, podle toho co je na webu je pandas oblíběnější než ndarray.

          Zkusím vysvětlit výhodu pandas dataframe:
          Chceš udělat backtest.
          Výpočet RSI: Vstup je pole hodnot bez datumů, výstup je jiné pole hodnot bez datumů.
          Pro SMA(5) dostaneš jiné pole hodnot, pro SMA(200) další pole hodnot. K tomu máš pole datumů.
          Takže abys zjistil cenu a idikátory pro nějaký datum, musíš iterovat přes 5 polí.

          Když to děláš přes pandas dataframe (nazvu ho df), máš to v paměti jako tabulku – první sloupec jsou datumy, druhý sloupec cena, třetí sloupec SMA(5), další SMA(200), další RSI2.

          Tohle mi vrátí řádek tabulky pro daný datum:

          day_slice = df.loc[df[‚date‘] == ‚2017-12-20‘]

          Hotovo. Žádné iterování přes pole.
          Nebo iteruješ přes celou tabulku řádek po řádku:

          day_slice = df.iloc(5) vrátí řádek s čílem 5

          Ale ta knihovna by asi šla použít pro výpočet indikátorů, které bych si přidal do dataframe nebo si to celé uložíš jako multimenzionální ndarray a ten bude asi mít taky nástroje jak udělat řez přes dimenzi.

    • admin napsal:

      Díky za výpočet RSI!

      ještě jsem našel tohle, prodávám, jak jsem koupil … https://www.quantopian.com/posts/technical-analysis-indicators-without-talib-code

  4. myk napsal:

    Tohle pracuje přímo s pandas, takže díky za link.

  5. blueowl napsal:

    Díky za upozornění na data od IEX a za shrnutí informací.

    Pro doplnění bych chtěl ještě uvést pár informací o IEX, které jsou velmi zajímavé.
    (Už to sice někdo zmínil v komentářích pod článkem „AOS v Pythonu jednoduše, snadno a rychle“, ale byla by škoda kdyby to zapadlo.)

    IEX je burza, kterou založil Brad Katsuyama [1], jako snahu o zprůhlednění trhů a obranu proti vysokofrekvenčním obchodníkům. Velmi čtivě to popisuje zmíněný Michael Lewis v knize Flash Boys (Jako blesk) [2], [3].
    Brad Katsuyama pokračuje v boji za férovější trhy i nadále. Loni v létě se například účastnil slyšení před Komisíí pro finanční služby spolu s představiteli hlavních amerických burz. [4], [5], [6]

    [1] https://en.wikipedia.org/wiki/Brad_Katsuyama
    [2] https://www.dokoran.cz/?p=book&id=842
    [3] http://blog.kniha.cz/recenze-knihy-michael-lewis-jako-blesk/
    [4] http://www.businessinsider.com/iex-there-is-clear-and-significant-harm-to-investors-2017-6
    [5] https://financialservices.house.gov/calendar/eventsingle.aspx?EventID=402034
    [6] https://iextrading.com/policy/testimony/2017/

  6. VM napsal:

    Jsou ty historicky data z IEXu adjustovany? Kdyz jsem si prochazel dokumentaci v tom prosinci, nabyl jsem dojmu, ze jo. Zejmena proto, ze v change logu je, ze ve verzi 1.0 (July 5, 2017) pridali pro endpoint „chart“ pole „unadjustedClose“. Bohuzel ho to ale nevraci. Adjustovany data pouzivam jen v backtestu, ale pro ostry provoz je tedy nepouzivam. Jak jste na tom Vy?

  7. mir++ napsal:

    Hezký no,,, to jsou výpočty letu do vesmíru??? To jde mimo mě, závidím, že to umíte. Já to zkoušel naposledy na průmce….. a už ujel vlak. A nemám sílu se to učit. Jste borci!!!

    • admin napsal:

      Ale ne, do toho by ses dostal jedna dvě. Všechny programovací jazyky jsou plusmínus podobný. A navíc náš AOS je až trapně jednoduchej na napsání v čemkoliv:

      1) Zjisti co koupit
      2) Kup to

      případně 3) mezitím nebo předtím něco prodej.

      Zbytek je vata a v tomto případě třeba shánění dat, kdo nám je dá rychle a levně. Žádná magie za tím není …

  8. Boris napsal:

    Ahoj, díky za tip za skvělý zdroj dat. Perfektní EOD, ale asi bude potřeba doplnit před zavíračkou o intradenní realtime data. Zkoušel jsem něco jako:
    https://api.iextrading.com/1.0/tops/last?symbols=all,spg,pg
    Asi celkem funkční cesta, čas je unixovy, milisekundy od 1.1.1970. Ale mám dojem, že některé tituly mají pár minut zpoždění. Například SPG. Na druhou stranu algoritmus devadesátky je tak robustní, že by to nemuselo vadit.
    Je i jiná cesta jak číst data z menším zpožděním? IQfeed, samozřejmě ;o)
    Chci se časem vyhnout domovské IB, poslední dobou dělají s daty hrozné šachy.
    Díky, ať se daří.

    • Robo napsal:

      Data su realtime, avsak ta burza obchoduje male percento vsetkych tradov a bud pozeras last realized price na IEXe, co moze byt naozaj x sekund mozno aj minut za poslednym obchodom, alebo si ratas stred medzi IEX Bid a IEX Ask. Niekedy su vsak tak daleko od seba, ze je to dost nepresne. Verim ze ku koncu dna ako obchody rastu su cisla presnejsie

Napsat komentář

Vaše emailová adresa nebude zveřejněna.