En la rutaEmpieza aquí3/4

Curso de Python Para Trading - Parte 1 : Datos de Mercado con OpenBB

Descarga gratuita de acciones, futuros, opciones y forex desde Python con OpenBB, y comparación del volumen entre proveedores.

Research-0014Actualizado 10 min

Fig. — Curva de futuros por vencimiento, en contango (ilustrativo)
Índice

Que es OpenBB

OpenBB es una plataforma open-source donde han integrado mas de 100 diferentes fuentes de datos, de todo tipo de asset clases, desde acciones, opciones, criptoactivos,forex, datos macroeconomicos y mucho mas. Dando opciones de acceso desde una App estilo Bloomberg, una consola CLI estilo old bloomberg,y dejando una puerta abierta a los programadores de python mediante su paquete openbb.

Historicamente acceder a datos financieros era un reto considerable, donde era caro, inaccesible y requeria demasiado tiempo. Desde OpenBB simplifican todo este proceso, centralizando en un unico punto, todas las fuentes de datos. Utilizando una unica libreria para obtener todos nuestros datos en tiempo real.

Instalacion de las librerias necesarias

Utilizando el stack dockerizado que hemos creado

GitHub - quantarmyz/quantstack: QUANTARMY quantstack | One-click quantitative envoirment based in docker, debian, conda, jupyterlabs,zipline-reloaded and arcticdb QUANTARMY quantstack | One-click quantitative envoirment based in docker, debian, conda, jupyterlabs,zipline-reloaded and arcticdb - quantarmyz/quantstack

cargamos el entorno que utilizamos desde un terminal, y ejecutamos el siguiente comando, que lo que hara, sera instalar el gateway en python que nos interconectara con openBB, pudiendo trabajar con toda la potencia de openBB desde python, de una forma extremadamente sencilla

!pip install openbb[all]

Primer Uso de OpenBB

Una vez descargada la libreria, al cargar por primera vez la libreria en python, descargara y instalara unos paquetes adicionales en segundo plano.

IN [01]python
from openbb import obb
obb.user.preferences.output_type = 'dataframe'

Una vez finalizado, se recomienda volver a cargar el kernel, y la libreria estara totalmente funcional.

Obteniendo datos Acciones

Comparando Datos Fundamentales

IN [02]python
obb.equity.fundamental.metrics("AAPL,MSFT").T
OUT [02]
01
symbolAAPLMSFT
market_cap3414690000000.03109760000000.0
pe_ratio34.235.45
foward_pe30.2627.23
eps6.5711.8
price_to_sales8.8612.69
price_to_book51.2511.58
book_value_per_share4.3836.11
price_to_cash55.2541.17
cash_per_share4.0610.16
price_to_free_cash_flow32.7341.98
debt_to_equity1.520.36
long_term_debt_to_equity1.290.31
quick_ratio0.911.27
current_ratio0.951.27
gross_margin0.45960.6976
profit_margin0.26440.3596
operating_margin0.31270.4464
return_on_assets0.30590.1907
return_on_investment0.66680.2508
return_on_equity1.60580.3713
payout_ratio0.15320.2542

Datos de Precio

IN [03]python
data = obb.equity.price.historical("SPY")

Si deseamos cambiar el timeframe, lo hacemos mediante el parametro interval

  • 1m = One Minute
  • 1h = One Hour
  • 1d = One Day
  • 1W = One Week
  • 1M = One Month

En este caso, lo dejamos por defecto, en timeframe diario.

openhighlowclosevolume
date
------------------
2004-01-02111.74112.19110.73111.2338072300
2004-01-05111.69112.52111.59112.4427959800
2004-01-06112.16112.73112.00112.5520472800
2004-01-07112.39113.06111.89112.9330170400
2004-01-08113.25113.41112.77113.3836438400
..................
2024-09-25571.19571.89568.91570.0437682308
2024-09-26574.49574.71569.90572.3044788926
2024-09-27573.42574.22570.42571.4741082707
2024-09-30570.50574.38568.08573.7659333099
2024-10-01573.41574.06566.00568.6270827736

5227 rows × 5 columns

Comparando Sectores de forma fundamental

IN [04]python
obb.equity.compare.groups(group="industry",metric="valuation").T
OUT [04]
0123456789...135136137138139140141142143144
namePharmaceutical RetailersInsurance - ReinsuranceREIT - MortgageCoking CoalAirlinesMarine ShippingFinancial ConglomeratesInsurance - LifePaper & Paper ProductsThermal Coal...BiotechnologyREIT - IndustrialREIT - SpecialtyUraniumREIT - ResidentialREIT - OfficeREIT - Healthcare FacilitiesShell CompaniesReal Estate - DiversifiedInfrastructure Operations
market_cap798000000050930000000585200000001027000000012670000000040150000000353700000003006400000001703000000011610000000...1302310000000301390000000425450000000334000000002017300000007659000000016375000000027320000000757000000034940000000
performance_1D0.02320.0024-0.0010.005-0.01790.0052-0.00360.01170.00770.0107...-0.0119-0.0122-0.00310.0214-0.0066-0.0011-0.0055-0.00180.0002-0.0111
forward_pe5.17.27.457.718.088.439.049.079.419.49...35.8739.9741.5547.8249.7656.366.47138.44147.61151.85
eps_growth_past_5_years-0.04820.5531-0.22140.0583-0.04310.21480.0292-0.01070.71620.1513...0.01230.07350.13080.19010.1472-0.2137-0.1288NaN0.1838NaN
eps_growth_next_5_years0.05690.07460.03130.06260.14920.09920.13860.08910.0839-0.0487...0.11870.01810.1124NaN0.01750.00680.3635NaN0.19750.1425
sales_growth_past_5_years0.03710.22180.35330.15650.24380.2487-0.00610.05540.16150.1014...2.82210.1921.15812.59590.08410.06510.11570.60250.20970.0814
volume353000011569063800001551301186000030300002864901810000211010326830...8948000014800002089999919000017200001920000361000010200002768095120
price_to_sales0.050.951.840.970.471.331.221.140.991.16...10.2112.227.3913.478.283.937.0826.24.813.34
price_to_book0.571.310.881.672.161.141.191.661.841.42...5.372.736.484.312.661.112.112.391.937.74
price_to_cash9.77NaN4.177.112.36.333.383292.143.839.08...6.7127.4942.5822.2256.668.7430.3540.937.398.61
price_to_free_cash_flow419.392.856.739.7128.049.463.744.8825.636.79...48.6725.9144.9398.9323.1613.9228.53109.472.2333.73
peNaN7.0124.38.3712.116.3111.0113.8349.527.37...55.9641.2246.1588.9344.8788.88112.8458.4695.4838.81
pegNaN0.947.771.340.810.640.791.555.9NaN...4.7222.754.11NaN25.58130.733.1NaN4.832.72

14 rows × 145 columns

Derivados Datos de una curva de Futuros

IN [05]python
data = obb.derivatives.futures.curve(symbol="VX")
OUT [05]
expirationprice
02024-1020.50
12024-1119.35
22024-1218.90
32025-0119.30
42025-0219.50
52025-0319.60
62025-0419.65
72025-0519.75
82025-0619.85

Plotear la curva

IN [06]python
import pandas as pd
data.index = pd.to_datetime(data.expiration)
data.plot()
OUT [06]

Descargar y plotear diferentes contratos

IN [07]python
expirations = [
    "2024-12",
    "2025-12",
    "2026-12",
    "2027-12",
    "2028-12",
    "2029-12",
    "2030-12",
]
IN [08]python
contracts = []
for expiration in expirations:
    df = (
        obb
        .derivatives
        .futures
        .historical(
            symbol="CL",
            expiration=expiration,
            start_date="2020-01-01",
            end_date="2022-12-31"
        )
    ).rename(columns={
        "close": expiration
            })
    contracts.append(df[expiration])
IN [09]python
historical = (
    pd
    .DataFrame(contracts)
    .transpose()
    .dropna()
)
IN [10]python
historical.plot()
OUT [10]

Obteniendo una cadena de opciones

Respecto a la cadena de opciones, las trataremos de forma separada en un proximo articulo, todas las posilibidades que proporciona OpenBB. Pero de momento, par snapear la cadena actual de un ticker en concreto, se realizaria de la siguiente forma

IN [11]python
chains = obb.derivatives.options.chains(symbol="SPY")
OUT [11]
underlying_symbolunderlying_pricecontract_symbolexpirationdtestrikeoption_typeopen_interestvolumetheoretical_price...lowprev_closechangechange_percentimplied_volatilitydeltagammathetavegarho
0SPY568.1201SPY241002C003000002024-10-020300.0call512268.1850...268.16269.485001-0.725-0.002690.00001.00000.0000-0.00240.00000.0000
1SPY568.1201SPY241002P003000002024-10-020300.0put1000.0001...0.000.0050000.0000.000007.06200.00000.0000-0.00010.00000.0000
2SPY568.1201SPY241002C003100002024-10-020310.0call00258.1850...0.00259.5350040.0000.000000.00001.00000.0000-0.00240.00000.0000
3SPY568.1201SPY241002P003100002024-10-020310.0put000.0002...0.000.0050000.0000.000006.71560.00000.0000-0.00020.00000.0000
4SPY568.1201SPY241002C003200002024-10-020320.0call00248.1850...0.00249.5149990.0000.000000.00001.00000.0000-0.00240.00000.0000
..................................................................
9863SPY568.1201SPY270115P008900002027-01-15835890.0put00321.8150...0.00320.5899960.0000.000000.2833-1.00000.0000-0.06400.00000.0000
9864SPY568.1201SPY270115C008950002027-01-15835895.0call000.8942...0.000.8750000.0000.000000.12430.02530.0006-0.00340.56540.2984
9865SPY568.1201SPY270115P008950002027-01-15835895.0put00326.8150...0.00325.5899960.0000.000000.2861-1.00000.0000-0.06400.00000.0000
9866SPY568.1201SPY270115C009000002027-01-15835900.0call22500.8464...0.000.9250000.0000.000000.12650.02400.0005-0.00330.54300.2836
9867SPY568.1201SPY270115P009000002027-01-15835900.0put00331.8150...0.00330.5899960.0000.000000.2888-1.00000.0000-0.06400.00000.0000

9868 rows × 29 columns

Descargando una opcion especifica

Si dentro de la cadena, queremos bajar un contrato en especifico, debemos tratarlo como si estuvieramos descargando un ticker de una accion, pero el simbolo es el identificador de la opcion. De la siguiente forma

IN [12]python
data = obb.equity.price.historical(
    symbol="SPY241220C00550000",
        provider="yfinance")
OUT [12]
openhighlowclosevolumesplit_ratiodividend
date
------------------------
2023-10-022.3400002.3400002.1400002.14000010040.00.0
2023-10-032.2400002.2400002.0100002.030000470.00.0
2023-10-042.0500002.2000002.0500002.20000040.00.0
2023-10-062.0300002.6000002.0300002.600000260.00.0
2023-10-092.5000002.7800002.5000002.780000190.00.0
........................
2024-09-2637.95999937.98000035.63000136.500000300.00.0
2024-09-2736.79000136.79000135.88000135.939999320.00.0
2024-09-3035.50000037.48000033.79999937.480000210.00.0
2024-10-0135.61999935.61999933.09000034.660000620.00.0
2024-10-0232.57000032.57000032.57000032.57000020.00.0

246 rows × 7 columns

Forex

IN [13]python
obb.currency.price.historical("usdjpy", provider="yfinance").to_df()
OUT [13]
openhighlowclosevolume
date
------------------
2023-08-22146.238007146.389999145.501999146.2380070.0
2023-08-23145.763000145.813004144.580002145.7630000.0
2023-08-24144.673004145.947006144.621002144.6730040.0
2023-08-25146.067001146.604996145.733994146.0670010.0
2023-08-28146.531006146.716003146.278000146.5310060.0
..................
2024-08-16149.222000149.229996147.639008149.2220000.0
2024-08-19147.955994147.959000145.220993147.9559940.0
2024-08-20146.699005147.319000145.533997146.6990050.0
2024-08-21145.347000146.339005144.981003145.3470000.0
2024-08-22145.117996146.524994144.839996146.2870030.0

Validacion de Datos.

Como extra, vamos a comparar los datos de diferentes proveedores, para poder tener una aproximacion de la calidad de los datos que estamos gestionando. Los datos son los inputs del proceso, y una materia prima de baja calidad, generara modelos de baja calidad. Para esta prueba, vamos a verificar el volumen, sobre el ticker QQQ (Nasdaq Composite ETF).

Para validad que los datos de los diferentes proveedores son correctos, deberiamos obtener el mismo volumen para todos los proveedores.

Primero vamos a recolectar los datos necesarios.

IN [14]python
yahoo = obb.equity.price.historical("QQQ", provider="yfinance").to_df()
alphavantage = obb.equity.price.historical("QQQ", provider="alpha_vantage").to_df()
intrinio = obb.equity.price.historical("QQQ", provider="intrinio").to_df()
fmp = obb.equity.price.historical("QQQ", provider="fmp").to_df()
polygon = obb.equity.price.historical("QQQ", provider="polygon").to_df()

Mediante el siguiente codigo, descargamos de diferentes proveedores el ticker QQQ en formato Pandas DataFrame.

Ahora procesamos los datos, creando un nuevo dataframe, con los ultimos 10 casos del volumen de los diferentes proveedores y eliminamos los valores NA

IN [15]python
compare = pd.DataFrame()
compare["AV Volume"] = alphavantage["volume"].tail(10)
compare["FMP Volume"] = fmp["volume"].tail(10)
compare["Intrinio Volume"] = intrinio["volume"].tail(10)
compare["Yahoo Volume"] = yahoo["volume"].tail(10)
compare["Polygon Volume"] = polygon["volume"].tail(10)

compare.dropna(how="any")
OUT [15]
AV VolumeFMP VolumeIntrinio VolumeYahoo VolumePolygon Volume
date
------------------
2024-08-094561955845619558.045619558.045619600.045425963.0
2024-08-124254206942542069.042542069.042542100.042533175.0
2024-08-135233307352333073.052333073.052333100.050110167.0
2024-08-144244692942446929.042446929.042446900.042362522.0
2024-08-156084681260846812.060846812.060846800.060762738.0
2024-08-164443072844430728.044430728.044430700.044368969.0
2024-08-193912179339121793.039121793.039121800.038648958.0
2024-08-203373226433732264.033732264.033732300.033693989.0
2024-08-214151460038682509.041514600.041467000.041532360.0

Como conclusion, podemos ver que no siempre coincide, asi que cada uno debe ejecutar sus procedimientos oportunos para saber que precio es real, y que precio no.

Conclusiones

Estos articulos cortos, pretenden ir al foco del tema en cuestion de una forma concentrada. Mediante este articulo, puedes acceder y descargar series temporales de diferentes asset clases, para posteriormente gestionarlas en nuestra datalake, o de la forma independendiente necesaria. Esta guía es la parte 1 del curso de trading algorítmico con Python, y también tienes la versión en inglés disponible.

Escrito por

Inversor desde 2014. Research desde 2017. He trabajado en diferentes gestoras de capital y Hedgefunds Crypto. Apasionado del codigo, los datos y las finanzas. Actualmente localizado en Ucrania.