Самый быстрый подход для чтения и обработки 10k Excell клеток в Python / Pandas? - PullRequest
0 голосов
/ 29 октября 2019

Я хочу читать и обрабатывать данные DDE в реальном времени с торговой платформы, используя Excel в качестве «моста» между торговой платформой (которая отправляет данные) и Python, который их обрабатывает, и распечатывать их обратно в Excel как интерфейсный интерфейс». СКОРОСТЬ НЕОБХОДИМА. Мне нужно:

  • прочитать 6/10 тысяч ячеек в Excel как можно быстрее

  • сумма тиков, пройденных одновременно (тот же час:м: сек)

  • проверка, содержит ли DataFrame какое-либо значение в статическом массиве (например, большие количества)

  • запись вывода в том же Excelфайл (другой лист), используемый в качестве внешнего интерфейса 'gui'.

Я импортировал библиотеку ' xlwings ' и использовал ее для чтения данных с одного листа, вычисления необходимых значений в python, а затем распечатки результатов на другом листе того жефайл. Я хочу, чтобы Excel был открытым и видимым, чтобы он функционировал как «панель вывода». Эта функция запускается в бесконечном цикле чтение цен акций в реальном времени.

import xlwings as xw
import numpy as np
import pandas as pd

...
...

tickdf = pd.DataFrame(xw.Book('datafile.xlsx').sheets['raw_data'].range((1,5)(1500, 8)).value)
tickdf.columns = ['time', 'price', 'all-tick','symb']
tickdf = tickdf[['time','symb', 'price', 'all-tick']]
#read data and fill a pandas.df with values, then re-order columns

try:
   global ttt #this is used as temporary global pandas.df
   global tttout #this is used as output global pandas.df copy
   #they are global as they can be zeroed with another function

   ttt= ttt.append(tickdf, ignore_index=False) 
   #at each loop, newly read ticks are added as rows to the end of ttt global.df.

   ttt.drop_duplicates(inplace=True)

   tttout = ttt.copy()
   #to prevent outputting incomplete data,for extra-safety, I use a copy of the ttt as DF to be printed out on excel file. I find this as an extra-safety step

   tttout = tttout.groupby(['time','symb'], as_index=False).agg({'all-tick':'sum', 'price':'first'})
   tttout = tttout.set_index('time')
   #sort it by time/name and set time as index

   tttout = tttout.loc[tttout['all-tick'].isin(target_ticker)] 
   #find matching values comparing an array of a dozen values

   tttout = tttout.sort_values(by = ['time', 'symb'], ascending = [False, True])
   xw.Book(file_path).sheets['OUTPUT'].range('B2').value = tttout

Я запускаю это на i5@4.2ghz, и эта функция вместе с другим небольшим другим кодом,работает за 500-600 мс на цикл, что довольно неплохо (но не фантастично!) - я хотел бы знать, если есть лучший подход и какие шаги могут быть узкими местами.

Код читает 1500 строкпо одному на каждую котируемую акцию в алфавитном порядке, каждый из которых является «последним тиком», принятым на рынке для данной конкретной акции, и выглядит так:

'10:00:04 | ABC | 10.33 | 50000'
'09:45:20 | XYZ | 5.260 | 200 '
'....

- время, символ акции, цена, количество.

Я хочу выяснить, есть ли на рынке какие-то конкретные количества, торгуемые на рынке, например, 1.000.000 (поскольку это огромный заказ), или, может быть, просто «1», как часто используется в качестве рыночного. 'heartbeat', своего рода фальшивый порядок.

Мой подход заключается в использовании метода Pandas / Xlwings / и 'isin'. Есть ли более эффективный подход, который может улучшить производительность моего скрипта?

Ответы [ 2 ]

0 голосов
/ 16 ноября 2019

@ Тони Робертс, спасибо

У меня есть одно сомнение и одно наблюдение.

СОМНЕНИЕ: данные обновляются очень быстро, каждые 50-100 мс. Будет ли возможно использовать функцию UDF, которая будет вызываться так часто? это будет худой? У меня мало опыта в этом.

НАБЛЮДЕНИЕ: PyXLL, безусловно, чрезвычайно мощный, хорошо сделанный, ухоженный, но ИМХО, стоит $ 25 / месяц, это выходит за рамки чистой природы бесплатного языка Python. Хотя я понимаю, что качество имеет цену.

0 голосов
/ 13 ноября 2019

Было бы быстрее использовать UDF, написанный на PyXLL, так как это позволило бы избежать прохождения через COM и внешний процесс. У вас будет формула в Excel с входным набором данных, который будет вызываться при каждом обновлении входных данных. Это позволило бы избежать необходимости опрашивать данные в бесконечном цикле и должно быть намного быстрее, чем запуск Python вне Excel.

См. https://www.pyxll.com/docs/introduction.html, если вы еще не знакомы с PyXLL.

PyXLL может преобразовать входной диапазон в DataFrame pandas для вас (см. https://www.pyxll.com/docs/userguide/pandas.html),, но это не самый быстрый способ сделать это.

Самый быстрый способ передачи данныхиз Excel в Python - через массив numpy с плавающей запятой, использующий тип «numpy_array» в PyXLL (см. https://www.pyxll.com/docs/userguide/udfs/argtypes.html#numpy-array-types).

Поскольку скорость вызывает беспокойство, возможно, вы могли бы разделить данные и получить некоторые функции, которые занимают в основномстатические данные (например, строки и заголовки столбцов) и другие функции, которые принимают переменные данные в виде numpy_arrays, где это возможно, или другие типы, если это не так, а затем заключительную функцию, объединяющую их все.

PyXLL может возвращать объекты Python в Excelкак объект обрабатывает. Если вам нужно вернуть промежуточные результаты, то, как правило, это сделать быстрее, чем расширять весь набор данных додиапазон Excel.

...