0
votes

Calculer efficacement le point de contrôle avec des pandas

Mon algorithme a progressé de 35 secondes à 15 minutes d'exécution lors de la mise en œuvre de cette fonctionnalité sur une période quotidienne. L'algo récupère l'historique quotidien en vrac et iTère sur un sous-ensemble du Dataframe (de T0 à TX où TX est la rangée actuelle d'itération). Cela fait ceci pour imiter ce qui se passerait pendant les opérations en temps réel de l'algo. Je sais qu'il y a des moyens d'améliorer la mémoire en utilisant la mémoire entre les calculs de cadre, mais je me demandais s'il y avait une implémentation plus pandas-ish qui verrait une prestation immédiate.

suppose que auto.step est quelque chose Comme 0.00001 et self.precision est 5 ; Ils sont utilisés pour la binning les informations de barre OHLC dans des étapes discrètes pour la recherche du POC. _Frame est un sous-ensemble de lignes de l'ensemble de laacrame et _low / _High est respectif à cela. Le bloc de code suivant exécute sur l'ensemble du _frame qui pourrait être supérieur à ~ 250 lignes chaque fois qu'il y a une nouvelle ligne ajoutée par l'algo (lors du calcul du calendrier annuel sur les données quotidiennes). Je crois que ce sont les iTerrows qui causent le ralentissement majeur. Le Dataframe a des colonnes telles que élevé , bas , Ouvrir , ferme , volume . Je calcule la possibilité de contrôle des prix du temps et du point de contrôle du volume. xxx


4 commentaires

Avez-vous des chances de poster des données d'exemple pour _frame? Je pense qu'il y a plusieurs choses que vous pourriez faire pour accélérer les choses, mais que vous voudrez que des données exécutent une analyse comparative.


Après un rapide Google: Github.com/matplotlib/sample_Data/blob/Master/aaply .csv


J'ai travaillé à ce sujet et je pense que vous devez revoir la logique de votre algorithme à deux égards. 1) Lorsque vous utilisez des prises _PRICE comme un index pour incrémenter time_prices. La tranchée ne comprend pas la dernière valeur, donc chaque fois que vous itérez _frame, vous manquez l'indice de valeur «High» en volume_Plus et à la fois. 2) On dirait que ceci est de calculer le prix moyen pondéré en volume de chaque jour. Je crois que les mathématiques pourraient être plus simples sans énormes données ni séries. J'ai révisé votre code et j'ai la même réponse beaucoup plus vite, mais que vous ressentez la réponse que vous obtenez n'est pas la réponse intention


VWAP n'est pas la même chose que VPOC. Le delta entre les deux varie +/- de 0,01 à 1,30 dans mon jeu de données de test pouvant être très pertinents pour les résultats attendus. J'ai testé les données de session VWAP et VWAP par rapport à Tradingview pour confirmer ceci.


3 Réponses :


0
votes

Vous pouvez utiliser cette fonction comme base et pour le régler: xxx


2 commentaires

Cela assume des données de tick, non? J'ai des barres OHLC; Il y a des prix dans ces barres que j'ai besoin de capturer.


Dans votre code,'Poc_volume 'calcule la somme du volume chez'Poc_price'. Ce n'est pas un VPOC. Le véritable volume POC est indépendant du prix POC



0
votes

J'ai réussi à y remédier à 2 minutes au lieu de 15 à 15 heures sur des délais quotidiens de toute façon. Il est toujours lent sur des délais plus faibles (10 minutes toutes les heures sur une période de 2 ans avec une précision de 2 pour actions). Travailler avec des données de données par opposition à la série était beaucoup plus lente. J'espère plus que je ne sais pas ce que je peux faire de côté à partir de la solution suivante:

# Upon class instantiation, I've created attributes for each timeframe
# related to `volume_at_price` and `time_at_price`. They serve as memory
# in between frame calculations
def _prices_at(self, frame, bars=0):
    # Include 1 step above high as np.arange does not
    # include the upper limit by default
    state = frame.iloc[-min(bars + 1, frame.index.size)]
    bins = np.around(np.arange(state.low, state.high + self.Step, self.Step), decimals=self.Precision)
    return pd.Series(state.volume / bins.size, index=bins)


# SetFeature/Feature implement timeframed attributes (i.e., 'volume_at_price_D')
_v = 'volume_at_price'
_t = 'time_at_price'

# Add to x_at_price histogram
_p = self._prices_at(frame)
self.SetFeature(_v, self.Feature(_v).add(_p, fill_value=0))
self.SetFeature(_t, self.Feature(_t).add(_p * 0 + 1, fill_value=0))

# Remove old data from histogram
_p = self._prices_at(frame, self.Bars)
v = self.SetFeature(_v, self.Feature(_v).subtract(_p, fill_value=0))
t = self.SetFeature(_t, self.Feature(_t).subtract(_p * 0 + 1, fill_value=0))

self.SetFeature('volume_poc', (v.idxmax() + v.iloc[::-1].idxmax()) / 2)
self.SetFeature('time_poc', (t.idxmax() + t.iloc[::-1].idxmax()) / 2)


0 commentaires

0
votes

Voici ce que j'ai travaillé. Je ne sais toujours pas que la réponse que vous produisez est correcte, je pense que votre ligne volume_prices [_prices] + = état.volume / _prices.Size code> n'est pas appliqué à chaque enregistrement dans Volume_Pas, mais Ici c'est avec l'analyse comparative. Environ une amélioration de 9x.

def vpOriginal():
    Step = 0.00001
    Precision = 5
    _frame = getData()
    _low = 85.0
    _high = 116.4
    # Set the complete index of prices +/- 1 step due to weird floating point precision issues
    volume_prices = pd.Series(0, index=np.around(np.arange(_low - Step, _high + Step, Step), decimals=Precision))
    time_prices = volume_prices.copy()
    time_prices2 = volume_prices.copy()
    for index, state in _frame.iterrows():
        _prices = np.around(np.arange(state.Low, state.High, Step), decimals=Precision)

        # Evenly distribute the bar's volume over its range
        volume_prices[_prices] += state.Volume / _prices.size
        # Increment time at price
        time_prices[_prices] += 1
    time_prices2 += 1
    # Pandas only returns the 1st row of the max value,
    # so we need to reverse the series to find the other side
    # and then find the average price between those two extremes
#    print(volume_prices.head(10))
    volume_poc = (volume_prices.idxmax() + volume_prices.iloc[::-1].idxmax() / 2)
    time_poc = (time_prices.idxmax() + time_prices.iloc[::-1].idxmax() / 2)
    return volume_poc, time_poc

def vpNoDF():
    Step = 0.00001
    Precision = 5
    _frame = getData()
    _low = 85.0
    _high = 116.4
    # Set the complete index of prices +/- 1 step due to weird floating point precision issues
    volume_prices = pd.Series(0, index=np.around(np.arange(_low - Step, _high + Step, Step), decimals=Precision))
    time_prices = volume_prices.copy()
    for index, state in _frame.iterrows():
        _prices = np.around((state.High - state.Low) / Step , 0)

        # Evenly distribute the bar's volume over its range
        volume_prices.loc[state.Low:state.High] += state.Volume / _prices
        # Increment time at price
        time_prices.loc[state.Low:state.High] += 1

    # Pandas only returns the 1st row of the max value,
    # so we need to reverse the series to find the other side
    # and then find the average price between those two extremes
    volume_poc = (volume_prices.idxmax() + volume_prices.iloc[::-1].idxmax() / 2)
    time_poc = (time_prices.idxmax() + time_prices.iloc[::-1].idxmax() / 2)
    return volume_poc, time_poc

getData()
Out[8]: 
         Date    Open    High     Low   Close    Volume  Adj Close
0  2008-10-14  116.26  116.40  103.14  104.08  70749800     104.08
1  2008-10-13  104.55  110.53  101.02  110.26  54967000     110.26
2  2008-10-10   85.70  100.00   85.00   96.80  79260700      96.80
3  2008-10-09   93.35   95.80   86.60   88.74  57763700      88.74
4  2008-10-08   85.91   96.33   85.68   89.79  78847900      89.79
5  2008-10-07  100.48  101.50   88.95   89.16  67099000      89.16
6  2008-10-06   91.96   98.78   87.54   98.14  75264900      98.14
7  2008-10-03  104.00  106.50   94.65   97.07  81942800      97.07
8  2008-10-02  108.01  108.79  100.00  100.10  57477300     100.10
9  2008-10-01  111.92  112.36  107.39  109.12  46303000     109.12

vpOriginal()
Out[9]: (142.55000000000001, 142.55000000000001)

vpNoDF()
Out[10]: (142.55000000000001, 142.55000000000001)

%timeit vpOriginal()
2.79 s ± 24.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit vpNoDF()
300 ms ± 8.04 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)


0 commentaires