Voici un échantillon des données:
Objectif:
créez une nouvelle colonne d'horodatage lorsque running_bid_max
supérieur ou égal à la valeur de ask_price_target_good
. Créez ensuite une colonne d'horodatage distincte lorsque running_bid_min
Est inférieur ou égal à ask_price_target_bad
.
Remarque : Cela sera effectué sur une grande quantité de données et de besoins calculés aussi rapidement que possible. J'espère ne pas avoir à parcourir toutes les lignes via iterrows()
running_bid_min
Et running_bid_max
Sont calculés à l'aide d'une running.min()
et pd.running.max()
à partir d'un certain laps de temps à l'avenir (cet exemple utilise une chronologie de 5 minutes. Ce sera donc le min, max 5 minutes de l'heure actuelle)
copiez les données ci-dessous puis utilisez df = pd.read_clipboard(sep=',')
time,bid_price,ask_price,running_bid_max,running_bid_min,ask_price_target_good,ask_price_target_bad
2019-07-24 07:59:44.432034,291.06,291.26,291.4,291.09,291.46,291.06
2019-07-24 07:59:46.393418,291.1,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:48.425615,291.1,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:50.084206,291.12,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:52.326455,291.12,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:54.428181,291.12,291.33,291.4,291.09,291.53,291.13
2019-07-24 07:59:58.550378,291.14,291.35,291.4,291.2,291.55,291.15
2019-07-24 08:00:00.837238,291.2,291.35,291.4,291.2,291.55,291.15
2019-07-24 08:00:57.338769,291.4,291.46,291.51,291.4,291.66,291.26
2019-07-24 08:00:59.058198,291.4,291.46,291.96,291.4,291.66,291.26
2019-07-24 08:01:00.802679,291.4,291.46,291.96,291.4,291.66,291.26
2019-07-24 08:01:02.781289,291.4,291.46,291.96,291.45,291.66,291.26
2019-07-24 08:01:04.645144,291.45,291.46,291.96,291.45,291.66,291.26
2019-07-24 08:01:06.491997,291.45,291.46,292.07,291.45,291.66,291.26
2019-07-24 08:01:08.586688,291.45,291.46,292.1,291.45,291.66,291.26
De votre question:
création d'une nouvelle colonne d'horodatage pour quand
running_bid_max
supérieur ou égal à la valeur dansask_price_target_good
. Créez ensuite une colonne d'horodatage distincte pour quandrunning_bid_min
est inférieur ou égal àask_price_target_bad
le problème semble trivial:
df['g'] = np.where(df.running_bid_max.ge(df.ask_price_target_good), df['time'], pd.NaT)
df['l'] = np.where(df.running_bid_min.le(df.ask_price_target_bad), df['time'], pd.NaT)
Ou est-ce que je manque quelque chose?
Mise à jour: vous voudrez peut-être ffill
et bfill
après les commandes ci-dessus:
df['g'] = df['g'].bfill()
df['l'] = df['l'].ffill()
Sortie, par exemple df['g']
:
0 2019-07-24 08:00:59.058198
1 2019-07-24 08:00:59.058198
2 2019-07-24 08:00:59.058198
3 2019-07-24 08:00:59.058198
4 2019-07-24 08:00:59.058198
5 2019-07-24 08:00:59.058198
6 2019-07-24 08:00:59.058198
7 2019-07-24 08:00:59.058198
8 2019-07-24 08:00:59.058198
9 2019-07-24 08:00:59.058198
10 2019-07-24 08:01:00.802679
11 2019-07-24 08:01:02.781289
12 2019-07-24 08:01:04.645144
13 2019-07-24 08:01:06.491997
14 2019-07-24 08:01:08.586688
Ce serait très bien si vous pouviez imprimer la sortie souhaitée. Sinon, je risque de manquer la logique.
Si vous travaillez sur une grande quantité de données, il est logique d'appliquer analyse à la vapeur *. (Cela sera assez efficace en mémoire et si vous utilisez cytoolz
même 2 à 4 fois plus vite)
Donc, fondamentalement, vous souhaitez partitionner vos données en fonction de l'une ou l'autre condition:
partitions = toolz.partitionby(lambda x: (x['running_bid_max'] >= x['ask_price_target_good']) or
(x['running_bid_min'] <= x['ask_price_target_bad']), data_stream)
Tout ce que vous ferez avec des partitions individuelles vous appartient (vous pouvez créer des champs ou des colonnes supplémentaires, etc.).
print([(part[0]['time'], part[-1]['time'],
part[0]['running_bid_max'] > part[0]['ask_price_target_good'],
part[0]['running_bid_min'] > part[0]['ask_price_target_bad'])
for part in partitions])
[('2019-07-24T07:59:46.393418', '2019-07-24T07:59:46.393418', False, False),
('2019-07-24T07:59:44.432034', '2019-07-24T07:59:44.432034', False, True),
('2019-07-24T07:59:48.425615', '2019-07-24T07:59:54.428181', False, False),
('2019-07-24T07:59:58.550378', '2019-07-24T08:00:57.338769', False, True),
('2019-07-24T08:00:59.058198', '2019-07-24T08:01:08.586688', True, True)]
Notez également qu'il est facile de créer des DataFrame
s individuels
info_cols = ['running_bid_max', 'ask_price_target_good', 'running_bid_min', 'ask_price_target_bad', 'time']
data_frames = [pandas.DataFrame(_)[info_cols] for _ in partitions]
data_frames
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.4 291.53 291.09 291.13 2019-07-24T07:59:46.393418
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.4 291.46 291.09 291.06 2019-07-24T07:59:44.432034
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.4 291.53 291.09 291.13 2019-07-24T07:59:48.425615
1 291.4 291.53 291.09 291.13 2019-07-24T07:59:50.084206
2 291.4 291.53 291.09 291.13 2019-07-24T07:59:52.326455
3 291.4 291.53 291.09 291.13 2019-07-24T07:59:54.428181
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.40 291.55 291.2 291.15 2019-07-24T07:59:58.550378
1 291.40 291.55 291.2 291.15 2019-07-24T08:00:00.837238
2 291.51 291.66 291.4 291.26 2019-07-24T08:00:57.338769
running_bid_max ask_price_target_good running_bid_min ask_price_target_bad time
0 291.96 291.66 291.40 291.26 2019-07-24T08:00:59.058198
1 291.96 291.66 291.40 291.26 2019-07-24T08:01:00.802679
2 291.96 291.66 291.45 291.26 2019-07-24T08:01:02.781289
3 291.96 291.66 291.45 291.26 2019-07-24T08:01:04.645144
4 292.07 291.66 291.45 291.26 2019-07-24T08:01:06.491997
5 292.10 291.66 291.45 291.26 2019-07-24T08:01:08.586688
Malheureusement, je n'ai pas trouvé de doublure pytition_by
pour DataFrame
. Il est sûrement caché quelque part. (Mais encore une fois, pandas
charge généralement toutes les données en mémoire - si vous souhaitez agréger pendant les E/S, la diffusion en continu peut être une solution.)
Par exemple, laissez-nous créer un simple flux csv
:
def data_stream():
with open('blubb.csv') as tsfile:
reader = csv.DictReader(tsfile, delimiter='\t')
number_keys = [_ for _ in reader.fieldnames if _ != 'time']
def update_values(data_item):
for k in number_keys:
data_item[k] = float(data_item[k])
return data_item
for row in reader:
yield update_values(dict(row))
qui produit une ligne traitée à la fois:
next(data_stream())
{'time': '2019-07-24T07:59:46.393418',
'bid_price': 291.1,
'ask_price': 291.33,
'running_bid_max': 291.4,
'running_bid_min': 291.09,
'ask_price_target_good': 291.53,
'ask_price_target_bad': 291.13}
Essaye ça:
df['g']=np.NaN
df['l']=np.NaN
deep=len(df.index)
irange= np.arange(1,deep)
for i in irange:
G=df.time[df.running_bid_max.shift(i)-df.ask_price_target_good>=0]
G.index=G.index-i
df['g']=df['g'].combine_first(G)
L=df.time[df.running_bid_min.shift(i)-df.ask_price_target_bad<=0]
L.index=L.index-i
df['l']=df['l'].combine_first(L)
Vous pouvez changer le paramètre profond (fenêtre de temps)
Il peut être optimisé
Je ne suis pas sûr de bien comprendre votre problème. Je fournis ci-dessous une solution au problème suivant:
running_bid_max
pourrait être supérieur à la valeur que nous avons dans le ask_price_target_good
colonne de la ligne couranterunning_bid_max
supérieur à ask_price_target_good
de la ligne actuelleDans votre exemple, pour la ligne 0
, on a 291.46
dans ask_price_target_good
. À la ligne 8
(dont le temps dans le délai de 5 minutes à partir de l'heure de la ligne0
), nous trouvons 291.51
(qui est supérieur à 291.46
) et nous souhaitons donc conserver cette valeur pour la ligne 0
.
Une opération symétrique doit être effectuée pour running_bid_min
qui doit être testé pour être inférieur à ask_price_target_bad
.
Pour résoudre ce problème, j'ai écrit le code suivant. Je n'utilise pas iterrows
mais la fonction apply
de DataFrame
. Néanmoins, je dois, pour chaque ligne, sélectionner un groupe de lignes dans l'ensemble de la trame de données (la fenêtre de temps de 5 minutes) avant de rechercher les lignes qui pourraient être supérieures à ask_price_target_good
. J'espère que ce sera assez rapide si vous avez de grandes trames de données.
import numpy as np
import pandas as pd
import datetime as dtm
data = pd.read_csv("data.csv", parse_dates=["time"])
TIME_WINDOW = 5*60
def over_target_good(row, dataframe):
time_window = dataframe.time <= (row.time
+ dtm.timedelta(seconds=TIME_WINDOW))
window_data = dataframe[time_window]
over_test = window_data.running_bid_max >= row.ask_price_target_good
over_data = window_data[over_test]
if len(over_data) > 0:
return over_data.running_bid_max[over_data.index[0]]
return np.NaN
def below_target_bad(row, dataframe):
time_window = dataframe.time <= (row.time
+ dtm.timedelta(seconds=TIME_WINDOW))
window_data = dataframe[time_window]
below_test = window_data.running_bid_min <= row.ask_price_target_bad
below_data = window_data[below_test]
if len(below_data) > 0:
return below_data.running_bid_min[below_data.index[0]]
return np.NaN
print("OVER\n", data.apply(over_target_good, axis=1, args=(data,)) )
print("BELOW\n", data.apply(below_target_bad, axis=1, args=(data,)) )
Objectif
création d'une nouvelle colonne d'horodatage pour quand
running_bid_max
supérieur ou égal à la valeur dansask_price_target_good
. Créez ensuite une colonne d'horodatage distincte pour quandrunning_bid_min
est inférieur ou égal àask_price_target_bad
Essaye ça :
import numpy as np
# Setup conditions
conditions = [
(df['running_bid_max'] >= df['ask_price_target_good']),
(df['running_bid_min'] >= df['ask_price_target_bad'])]
# Setup output (you could insert timestamp var here)
choices = ["Greater", "Lesser"]
# Apply conditions
df['bid_value'] = np.select(conditions, choices, default='N/A')
J'espère que cela aide à fournir une solution :)
D'accord, donc je pense que je comprends. Vous souhaitez que la valeur de chaque ligne soit l'horodatage de la prochaine date à laquelle ces conditions sont remplies? Si c'est le cas, vous pouvez construire à partir de la réponse de Quang. Plus précisément, laisse encore faire
df['g'] = np.where(df.running_bid_max.ge(df.ask_price_target_good), df['time'], pd.NaT)
df['l'] = np.where(df.running_bid_min.le(df.ask_price_target_bad), df['time'], pd.NaT)
Maintenant, nous pouvons faire:
df['g'] = df['g'].fillna(method='bfill')
df['l'] = df['l'].fillna(method='bfill')
Vous vous retrouvez maintenant avec l'horodatage de la ligne 9 à la ligne 0.
Est-ce ce que vous recherchez?