5. Fuente de datos local: objeto DataSource
La fuente de datos local es el núcleo de la funcionalidad de gestión de datos de qteasy. Todos los datos primero deben descargarse y guardarse en la fuente de datos local antes de que qteasy pueda utilizarlos. qteasy utiliza objetos DataSource para administrar la fuente de datos local. La fuente de datos local es similar a una base de datos y contiene una serie de tablas de datos predefinidas. La clase DataSource proporciona una serie de API para administrar los datos en las tablas de datos, incluida la lectura, actualización, eliminación y consulta de datos.
Para crear un nuevo objeto DataSource, puede utilizar el siguiente comando:
>>> import qteasy as qt
>>> ds = qt.DataSource()
Al imprimir el objeto DataSource, puede ver sus propiedades más básicas:
>>> print(ds)
file://csv@qt_root/data/
Desde la cadena impresa file://csv@qt_root/data/ de DataSource, podemos ver sus propiedades básicas.
Los resultados impresos contienen información básica sobre el objeto de origen de datos:
file:: el tipo de fuente de datos.qteasyadmite dos tipos de fuentes de datos: basadas en archivos y basadas en bases de datos.filesignifica que todas las tablas de datos de la fuente de datos se almacenan en el disco como archivos. De manera similar, los datos también se pueden almacenar en una base de datosmysql, en cuyo caso el código del tipo de fuente de datos esdb.csv:- Formato para guardar el archivo de datos.qteasypuede guardar archivos de datos en el disco en diferentes formatos. El formato más básico escsv, pero los usuarios también pueden guardar datos como archivoshdfyfth(feather) para satisfacer diferentes preferencias de rendimiento.qt_root/data/:: la ruta para guardar archivos de datos.qt_rootrepresenta la ruta raíz de instalación deqteasy. De forma predeterminada, todos los archivos de datos se guardan en el subdirectorio/data/en el directorio raíz.
De manera similar, puede crear un objeto de fuente de datos con el tipo de almacenamiento de datos «base de datos» y ver sus propiedades básicas. Sin embargo, al crear una fuente de datos de tipo «base de datos», debe especificar el nombre de host, el nombre de usuario, la contraseña y/o el nombre de la base de datos MySQL a la que desea conectarse.
>>> ds_db = qt.DataSource(source_type='database', host='localhost', user='您的用户名', password='您的密码', db_name='test_db')
>>> print(ds_db)
db:mysql://localhost@3306/test_db
De manera similar, los resultados impresos contienen información básica sobre la fuente de datos:
db:mysql: el tipo de fuente de datos es una base de datos MySQL; Todas las tablas de datos se almacenan en esta base de datos.localhost– el nombre de host de la base de datos3306– Puerto de conexión a la base de datostest_db: nombre de la base de datos. Si no se especifica ningún nombre, la base de datos predeterminada esqt_db, pero esta base de datos debe crearse de antemano.
Los diferentes objetos de fuente de datos, si tienen diferentes métodos y rutas de almacenamiento, no tendrán ninguna relación entre sí y no interferirán con los datos de los demás. Sin embargo, si dos fuentes de datos apuntan a la misma ruta y tienen el mismo tipo de archivo, almacenarán datos duplicados.
Para ver propiedades más básicas de la fuente de datos, puede acceder a varias propiedades del objeto de fuente de datos:
>>> print(ds.source_type) # 数据源的类型
file
>>> print(ds_db.source_type)
db
>>> print(ds.file_type, ds.file_path) # 数据源的文件类型和存储路径
csv /Users/jackie/Projects/qteasy/qteasy/data/
>>> print(ds.connection_type, ds_db.connection_type) # 数据源的连接类型
file://csv@qt_root/data/ db:mysql://localhost@3306/test_db
5.1. Fuente de datos predeterminada
qteasy tiene una fuente de datos predeterminada incorporada que no requiere creación manual por parte del usuario. De forma predeterminada, todos los datos se guardan y se leen desde esta fuente de datos predeterminada. Los usuarios pueden configurar los parámetros de esta fuente de datos a través del archivo de configuración de qteasy, asegurando que la fuente de datos apunte a la ruta correcta o que se utilice el nombre de usuario correcto para iniciar sesión en la base de datos correcta. Las propiedades de la fuente de datos predeterminada integrada se pueden ver utilizando el siguiente método:
>>> print(qt.QT_DATA_SOURCE)
db:mysql://www.qteasy.online@3306/ts_db
5.2. Ver tabla de datos
Después de comprender las propiedades básicas del objeto de la fuente de datos, el siguiente paso es comprender mejor los datos almacenados en la fuente de datos.
Todas las tablas de datos de la fuente de datos están predefinidas. Cada tabla de datos almacena un tipo diferente de datos. Estos datos cubren una gran cantidad de datos, incluida información básica, datos de la línea K, informes de desempeño de empresas que cotizan en bolsa, datos macroeconómicos, etc., para diversos productos de inversión como acciones, índices, fondos, futuros y opciones en los mercados de valores y mercados de futuros de Shanghai y Shenzhen. Para obtener una lista completa de tablas de datos, consulte el siguiente capítulo. Esta sección presenta principalmente cómo ver la información y los datos básicos de varias tablas de datos.
La lista de tablas en una fuente de datos se puede obtener a través de la propiedad all_tables de la fuente de datos, que devuelve un objeto de lista que contiene todas las tablas predefinidas en la fuente de datos. Sin embargo, es fundamental aclarar que, si bien muchas tablas están definidas en la fuente de datos, solo tienen definiciones básicas: la información del encabezado, los nombres de los campos, los significados de los campos y los tipos de datos están definidos. Las fuentes de datos recién creadas suelen tener tablas vacías que no contienen datos. Para ver qué tablas de la fuente de datos ya contienen datos, debe utilizar la función get_table_info().
>>> print('All tables in datasource:', len(ds.all_tables))
All tables in datasource: 108
>>> print('Some tables:', ds.all_tables[5:15])
Some tables: ['hk_trade_calendar', 'us_trade_calendar', 'stock_basic', 'hk_stock_basic', 'us_stock_basic', 'stock_names', 'stock_company', 'stk_managers', 'new_share', 'money_flow']
Como puede verse, la versión actual de qteasy predefine 108 tablas de datos, algunas de las cuales tienen nombres como stock_basic.
Para ver los detalles de una tabla específica en la fuente de datos actual, como su definición y si contiene datos, utilice el método get_table_info().
>>> info = ds.get_table_info('stock_basic')
<stock_basic>--<股票基本信息>
852KB/5K records on disc
primary keys:
----------------------------------------
1: ts_code: <5396> entries
starts: 000001.SZ, end: 920128.BJ
columns of table:
------------------------------------
columns dtypes remarks
0 ts_code varchar(9) 证券代码
1 symbol varchar(6) 股票代码
2 name varchar(20) 股票名称
3 area varchar(10) 地域
4 industry varchar(10) 所属行业
5 fullname varchar(50) 股票全称
6 enname varchar(120) 英文全称
7 cnspell varchar(40) 拼音缩写
8 market varchar(6) 市场类型
9 exchange varchar(6) 交易所代码
10 curr_type varchar(6) 交易货币
11 list_status varchar(4) 上市状态
12 list_date date 上市日期
13 delist_date date 退市日期
14 is_hs varchar(2) 是否沪深港通
La información impresa incluye el nombre de la tabla, la descripción, las definiciones de los campos y los tipos de datos.
Vale la pena señalar que si la tabla de datos ya está llena de datos, mostrará el tamaño actual de la tabla. En el ejemplo anterior, a continuación se explica cierta información clave:
852KB/5K records on disc: esto indica que la tabla ocupa aproximadamente 852 KB de espacio en disco y contiene aproximadamente 5000 filas de datos.primary keys: muestra las columnas de clave principal de los datos. Aquí, indica que la columnats_codees la clave principal de la tabla y esta columna tiene aproximadamente 5396 registros distintos. Si la tabla tiene varias claves principales, cada columna de clave principal se enumerará por separado, junto con el rango de datos para ese campo. Por ejemplo, en el ejemplo anterior, el rango de datos para la columnats_codees de000001.SZa920128.BJ, lo que nos permite saber que la tabla de información bursátil básica contiene información sobre más de 5000 acciones con códigos del 000001 al 920128.columns of table: esto muestra las definiciones de campo de la tabla de datos, que es elschemade la tabla. Enumera el nombrecolumns, el tipo de datosdtypesy la información descriptivaremarkspara cada columna.
Además, el método get_table_info() devuelve un dict, que también contiene información sobre la tabla. Esta información se puede imprimir y comparar con la información formateada descrita anteriormente para una mejor comprensión.
>>> print(info)
{'table': 'stock_basic', 'table_exists': True, 'table_size': '852KB', 'table_rows': '5K', 'primary_key1': 'ts_code', 'pk_records1': 5396, 'pk_min1': '000001.SZ', 'pk_max1': '920128.BJ', 'primary_key2': None, 'pk_records2': None, 'pk_min2': None, 'pk_max2': None}
5.3. Ver información general sobre la fuente de datos
Utilice los métodos anteriores para inspeccionar cada tabla; overview() resume todo el DataSource:
>>> overview = ds.overview()
Analyzing local data source tables... depending on size of tables, it may take a few minutes
[########################################]104/104-100.0% A...zing completed!
Finished analyzing datasource:
file://csv@qt_root/data/
3 table(s) out of 104 contain local data as summary below, to view complete list, print returned DataFrame
===============================tables with local data===============================
Has_data Size_on_disk Record_count Record_start Record_end
table
trade_calendar True 1.8MB 70K CFFEX SZSE
stock_basic True 852KB 5K None None
stock_daily True 98.8MB 1.3M 20211112 20241231
Ver la información general de toda la fuente de datos puede llevar varios minutos porque requiere resumir toda la información de cada tabla de datos.
Durante la descripción general, qteasy muestra una barra de progreso, luego devuelve un DataFrame de todas las tablas e imprime estadísticas clave.
El resumen muestra tres tablas completas (trade_calendar, stock_basic, stock_daily) con recuentos de filas, uso del disco y fechas de inicio/finalización. Imprima el DataFrame devuelto para ver todas las tablas:
>>> print(overview)
has_data size records pk1 records1 min1 \
table
trade_calendar True 1.8MB 70K cal_date 12865 19901012
hk_trade_calendar False 0 0 cal_date unknown N/A
us_trade_calendar False 0 0 cal_date unknown N/A
stock_basic True 852KB 5K ts_code 5396 000001.SZ
hk_stock_basic False 0 0 ts_code unknown N/A
... ... ... ... ... ... ...
cn_cpi False 0 0 month unknown N/A
cn_ppi False 0 0 month unknown N/A
cn_money False 0 0 month unknown N/A
cn_sf False 0 0 month unknown N/A
cn_pmi False 0 0 month unknown N/A
max1 pk2 records2 min2 max2
table
trade_calendar 20251231 exchange 7 CFFEX SZSE
hk_trade_calendar N/A None None None None
us_trade_calendar N/A None None None None
stock_basic 920128.BJ None None None None
hk_stock_basic N/A None None None None
... ... ... ... ... ...
cn_cpi N/A None None None None
cn_ppi N/A None None None None
cn_money N/A None None None None
cn_sf N/A None None None None
cn_pmi N/A None None None None
[104 rows x 11 columns]
5.4. La tabla de datos más importante.
En el primer uso, las tablas suelen estar vacías; por diseño, qteasy simplifica la adquisición y el uso de datos financieros.
Los datos básicos son fáciles de descargar, pero algunas tablas son más críticas; complételas primero porque otras dependen de ellas y del propio qteasy:
trade_calendar— Calendario de operaciones para todos los intercambios (día de negociación, código/nombre del intercambio). Principal de qteasy: muchas funciones fallan o se ralentizan sin él. Se utiliza para determinar los días de negociación y los rangos de fechas de descarga. Complete esta tabla primero.stock_basic— Tabla básica de acciones con código, nombre, fechas de cotización/eliminación de la lista, industria, región, etc. Base para tablas financieras y de línea K diaria de acciones; priorizar llenar esta tabla.index_basic: tabla básica del índice con código, nombre, fechas de publicación/eliminación de la lista, etc. Base para la línea K diaria del índice y tablas de constituyentes; priorizar llenar esta tabla.fund_basic— Tabla básica de fondos con código, nombre, tipo, tamaño, etc. Base para tablas diarias de línea K y NAV de fondos; priorizar llenar esta tabla.
Una vez que se completan estas tablas clave, la mayoría de las funciones de datos de qteasy funcionan sin problemas.
qteasy también define cuatro tablas del sistema para registros de operaciones en vivo:
sys_op_live_accounts: tabla maestra de cuenta comercial real con ID de cuenta, nombre, tipo, estado, etc.sys_op_positions: tabla de posiciones en vivo con ID de cuenta, código/nombre de seguridad, cantidad, costo, etc.sys_op_trade_orders: tabla de pedidos en vivo con ID de cuenta, hora/tipo de pedido, código de seguridad, cantidad, precio, etc.sys_op_trade_results: tabla de llenado en vivo con ID de cuenta, tiempo de llenado, código de seguridad, cantidad, precio, etc.
Estas cuatro tablas del sistema sustentan el comercio en vivo; los datos se generan automáticamente: no los complete, vea ni elimine manualmente.
Otras mesas
Además de las tablas clave, DataSource define muchas más que cubren conceptos básicos, línea K diaria, finanzas, dividendos, informes de ganancias, datos macro, etc.:
Tablas de datos de mercado: OHLCV en varias frecuencias para acciones, fondos e índices
Tablas básicas: acciones, fondos, índices, futuros, opciones, etc.
Tablas de indicadores: indicadores técnicos, fundamentales, macro, etc.
Tablas de estados financieros: balance, cuenta de resultados, flujo de caja, etc.
Tablas de informes de ganancias: informes rápidos, orientación de ganancias, pronósticos, etc.
Tablas de dividendos y operaciones en bloque: dividendos, operaciones en bloque, operaciones con accionistas, etc.
Tablas de referencia: macro, industria, intercambio y otros datos de referencia
Consulte get_table_info() o el siguiente capítulo para conocer las definiciones de tablas y los tipos de datos.
5.5. Leer datos de tablas
Una vez completado, use read_table_data() para leer con filtros de fecha/código sin preocuparse por los detalles de almacenamiento.
Para evitar lecturas enormes, pase siempre los filtros. Con read_table_data() puedes filtrar por código de seguridad y rango de fechas:
shares: Un código de seguridad o códigos separados por comas. Si la clave principal incluye un código de seguridad, filtre la salida por esos códigos.start: una fecha en formato“YYYYMMDD”. Si la clave principal de la tabla incluye hora o fecha, filtre las filas entrestartyend;start/enddeben proporcionarse como un parend: una fecha en formato“YYYYMMDD”. Si la clave principal de la tabla incluye hora o fecha, filtre las filas entrestartyend;start/enddeben proporcionarse como un par
DataSource filtra datos automáticamente según sus criterios, por ejemplo:
Lea los datos diarios de la línea K para 000651.SZ de stock_daily entre 2024-01-01 y 2024-01-15:
>>> ds.read_table_data(table='stock_daily', shares='000651.SZ', start='20240101', end='20240115')
open high low ... pct_chg vol amount
ts_code trade_date ...
000651.SZ 2024-01-03 32.00 32.08 31.70 ... -0.7181 254468.92 810315.013
2024-01-04 31.90 32.01 31.45 ... 0.4717 333398.05 1057458.411
2024-01-08 33.12 33.21 32.85 ... -0.2426 415911.34 1372722.050
2024-01-02 32.17 32.20 31.96 ... -0.4352 253797.30 814257.175
2024-01-15 33.45 33.95 33.42 ... 0.6544 295681.34 996815.725
2024-01-11 33.66 33.82 33.42 ... -0.2376 284088.74 955075.100
2024-01-09 32.81 33.55 32.65 ... 1.7933 438207.66 1454959.637
2024-01-10 33.35 33.84 33.28 ... 0.5375 366485.52 1233441.572
2024-01-12 33.50 33.83 33.42 ... 0.0893 224012.73 753931.821
2024-01-05 32.05 33.29 31.62 ... 3.2238 832156.75 2738167.636
[10 rows x 9 columns]
DataSource aplica los filtros correctos para cada tabla e ignora los parámetros innecesarios. Por ejemplo, al consultar información básica de dos acciones, no se requiere la fecha de negociación: qteasy ignora start/end con un aviso. El parámetro shares también funciona para fondos, índices, futuros y opciones, no solo para acciones:
>>> ds.read_table_data(table='stock_basic', shares='000651.SZ,000700.SZ', start='20240101', end='20240131')
/Users/jackie/Projects/qteasy/qteasy/database.py:1314: RuntimeWarning: list index out of range
can not find date-like primary key in the table stock_basic!
passed start(2024-01-01) and end(2024-01-31) arguments will be ignored!
warnings.warn(msg, RuntimeWarning)
symbol name area industry ... list_status list_date delist_date is_hs
ts_code ...
000651.SZ 651 格力电器 广东 家用电器 ... L 19961118 NaN S
000700.SZ 700 模塑科技 江苏 汽车配件 ... L 19970228 NaN S
[2 rows x 14 columns]
Consulte la referencia de DataSource para obtener más información sobre read_table_data().
5.6. Agregar datos a tablas
Las lecturas fallan si las tablas están vacías o son insuficientes; llene las tablas primero.
Tenga en cuenta:
Esto cubre únicamente escrituras manuales; La descarga, limpieza y recarga automáticas se tratan más adelante.
Rellenar tablas mediante update_table_data(), escribiendo un DataFrame con tres parámetros:
table: Nombre de la tabla de destino en la que escribirdf: UnDataFrameque contiene datos para escribir en una tablamerge_type: Si esupdate, actualice las filas existentes en la tabla; si esignore, omita las filas duplicadas.
Con update_table_data(), no se requiere una coincidencia exacta del esquema: qteasy normaliza el formato y elimina duplicados antes de escribir.
Los datos de muestra se escriben a continuación solo para demostración.
>>> import pandas as pd
>>> df = pd.DataFrame({
... 'ts_code': ['000001.SZ', '000002.SZ', '000003.SZ', '000004.SZ', '000005.SZ',
... '000001.SZ', '000002.SZ', '000003.SZ', '000004.SZ', '000005.SZ'],
... 'trade_date': ['20211112', '20211112', '20211112', '20211112', '20211112',
... '20211113', '20211113', '20211113', '20211113', '20211113'],
... 'open': [1., 2., 3., 4., 5., 6., 7., 8., 9., 10.],
... 'high': [2., 3., 4., 5., 6., 7., 8., 9., 10., 1.],
... 'low': [3., 4., 5., 6., 7., 8., 9., 10., 1., 2.],
... 'close': [4., 5., 6., 7., 8., 9., 10., 1., 2., 3.]
... })
>>> print(df)
ts_code trade_date open high low close
0 000001.SZ 20211112 1.0 2.0 3.0 4.0
1 000002.SZ 20211112 2.0 3.0 4.0 5.0
2 000003.SZ 20211112 3.0 4.0 5.0 6.0
3 000004.SZ 20211112 4.0 5.0 6.0 7.0
4 000005.SZ 20211112 5.0 6.0 7.0 8.0
5 000001.SZ 20211113 6.0 7.0 8.0 9.0
6 000002.SZ 20211113 7.0 8.0 9.0 10.0
7 000003.SZ 20211113 8.0 9.0 10.0 1.0
8 000004.SZ 20211113 9.0 10.0 1.0 2.0
9 000005.SZ 20211113 10.0 1.0 2.0 3.0
El ejemplo DataFrame anterior se escribirá en index_daily. Actualmente index_daily está vacío y su schema difiere ligeramente del DataFrame:
El esquema de la tabla
index_dailydefine 11 columnas, mientras que el ejemploDataFrameanterior tiene solo 6; todas las columnasDataFrametodavía están dentro delindex_dailyschema.La tabla
index_dailyestá actualmente vacía y no se han completado datos.
>>> info = ds.get_table_info('index_daily')
<index_daily>--<指数日线行情>
0 MB/0 records on disc
primary keys:
----------------------------------------
1: ts_code: <unknown> entries
starts: N/A, end: N/A
2: trade_date: <unknown> entries
starts: N/A, end: N/A
columns of table:
------------------------------------
columns dtypes remarks
0 ts_code varchar(20) 证券代码
1 trade_date date 交易日期
2 open float 开盘价
3 high float 最高价
4 low float 最低价
5 close float 收盘价
6 pre_close float 昨收价
7 change float 涨跌额
8 pct_chg float 涨跌幅
9 vol double 成交量(手)
10 amount double 成交额(千元)
A continuación escribimos datos; Si tiene éxito, el método devuelve filas escritas:
>>> ds.update_table_data(table='index_daily', df=df)
10
Después de escribir, podemos volver a leer los datos que acabamos de insertar.
Muchas columnas se leen como NaN porque el df escrito no incluía esos campos.
>>> df = ds.read_table_data('index_daily', shares='000001.SZ, 000002.SZ')
>>> print(df)
open high low close pre_close change pct_chg vol \
ts_code trade_date
000001.SZ 2021-11-12 1.0 2.0 3.0 4.0 NaN NaN NaN NaN
000002.SZ 2021-11-12 2.0 3.0 4.0 5.0 NaN NaN NaN NaN
000001.SZ 2021-11-13 6.0 7.0 8.0 9.0 NaN NaN NaN NaN
000002.SZ 2021-11-13 7.0 8.0 9.0 10.0 NaN NaN NaN NaN
amount
ts_code trade_date
000001.SZ 2021-11-12 NaN
000002.SZ 2021-11-12 NaN
000001.SZ 2021-11-13 NaN
000002.SZ 2021-11-13 NaN
5.7. Mesa desplegable: tenga cuidado; ¡¡La eliminación es irreversible!!
También puede eliminar tablas enteras: qteasy no admite eliminaciones parciales; ten mucho cuidado.
DataSource está optimizado para almacenamiento y lecturas, no para eliminaciones frecuentes: es un almacén de datos, no una base de datos general.
¡El método DataSource drop_table_data() elimina una tabla completa y no se puede deshacer!
Para evitar caídas accidentales, se crean errores drop_table_data() de forma predeterminada, p. al eliminar datos temporales index_daily:
>>> ds.drop_table_data('index_daily')
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
Cell In[19], line 1
----> 1 ds.drop_table_data('index_daily')
File ~/Projects/qteasy/qteasy/database.py:1587, in DataSource.drop_table_data(self, table)
1584 if not self.allow_drop_table:
1585 err = RuntimeError('Can\'t drop table from current datasource according to setting, please check: '
1586 'datasource.allow_drop_table')
-> 1587 raise err
1589 if self.source_type == 'db':
1590 self._drop_db_table(db_table=table)
RuntimeError: Can't drop table from current datasource according to setting, please check: datasource.allow_drop_table
Establezca allow_drop_table en True para permitir caídas; Vuelva a configurarlo en False después.
El siguiente código cae index_daily; luego las lecturas de esa tabla fallan:
>>> ds.allow_drop_table = True
>>> ds.drop_table_data('index_daily')
>>> ds.allow_drop_table = False
>>> df = ds.read_table_data(table='index_daily')
>>> print(df)
Empty DataFrame
Columns: []
Index: []
5.8. Resumen
Ahora entendemos DataSource, la clase principal de qteasy para la gestión de datos del historial financiero, que incluye:
¿Qué es
DataSourcey cómo crear uno?Extrayendo datos de DataSource
Trabajando con DataSource
Los capítulos posteriores cubren más:
¿Qué datos financieros útiles hay en DataSource?
¿Cómo descargar y completar por lotes DataSource?
¿Extraer información de DataSource de forma más eficaz?