Partage
  • Partager sur Facebook
  • Partager sur Twitter

Trouver les intersections de deux courbes

Sujet résolu
    23 mars 2022 à 23:46:42

    Salut la communauté !

    Je viens avec un problème que je trouve un peu singulier. Je cherche a faire un algorithme capable de déterminer quand 2 courbes se croisent puis d'effectuer une action simple comme une incrémentation (pour compter le nombre de fois que les courbes se croisent par exemple) ou déclencher une fonction.

    La première courbe est sorte de sinusoïde variant entre -1 et 1 et dont les valeurs sont stockées dans une liste. La deuxième courbe est une simple droite de valeur 0.

    La difficulté du problème est que j'ai besoin que l'algorithme reconnaisse quand les 2 courbes se croisent mais également si la sinusoïde est croissante ou décroissante.

    La solution que j'ai en tête actuellement reviendrait à parcourir les valeurs de la courbe 1 avec une boucle FOR et a comparer les valeurs n et n-1 via une condition de la forme :

    IF n > n -1 AND n>0 AND n-1  <0 alors blablabla la sinusoïde coupe l'axe 0 de façon croissante

    ELSE n < n-1 AND n <0 and N-1 > 0 alors blablabla, la sinusoïde coupe l,axe 0 de façon croissante

    Le problème est que je suis incapable de comparer les valeurs de ma sinusoide.

    Une alternative à ce problème pourrait également être de générer une deuxième liste dont les valeurs seraient toutes décalées de 1 par rapport a ma sinusoide et de comparer directement les valeurs entre les 2 listes.

    J'ai essayé de résumer tout ça en un schéma car je me rends compte que ce n'est pas forcément clair :

    Merci a tous ceux qui apporterons leur pierre à l'édifice !

    • Partager sur Facebook
    • Partager sur Twitter
      24 mars 2022 à 0:54:46

      Tu l'as dit, les valeurs d'une sinusoïde varient entre -1 et +1.
      Si les valeurs sont suffisamment nombreuses et sur un intervalle suffisamment grand,
      on peut déterminer si la sinusoïde coupe l'axe des X en faisant:
      if (val[i-1] < 0 and val[i] > 0) or (val[i-1] > 0 and val[i] < 0):
          # On a croisé l'axe des X
      Pour déterminer si la fonction est croissante:
      if val[i-1] < val[i]:
          # la fonction est croissante.:
      -
      Si tu ne veux compter que les croisements quand la fonction est croissante:
      if val[i-1] < val[i] and val[i-1] < 0 and val[i] > 0:
          # Croisement quand la fonction est croissante.

      En fait, si val[i-1] < 0 et val[i] > 0, c'est évident que la fonction est croissante, donc:

      if val[i-1] < 0 and val[i] > 0:

          # Croisement quand la fonction est croissante.

      -
      from math import *
      liste = [sin(i*pi/1000) for i in range(1000000+2)]   # Pour dépasser un peu la dernière borne.
      count = 0
      for i in range(1, len(liste)):
          if liste[i-1] < 0 and liste[i] > 0:
              count += 1
      print(count)
      -
      500

      -
      Edité par PierrotLeFou 24 mars 2022 à 2:30:41

      • Partager sur Facebook
      • Partager sur Twitter

      Le Tout est souvent plus grand que la somme de ses parties.

        24 mars 2022 à 5:37:05

        Saut PierrotLeFou, merci pour ta réponse, c'est beaucoup plus simple que ce que je pensais !

        Actuellement ça me donne ça :

        ROC étant mes points de la courbes "sinusoidale"

        for i in range(1, len(df['ROC']+2)):
            if df['ROC'][i-1] < 0 and df['ROC'][i] > 0:
                longTrade =True
                df['LT'] = longTrade
            elif df['ROC'][i-1] > 0 and df['ROC'][i] < 0:
                shortTrade = True
                df['ST'] = shortTrade
            else:
                longTrade =False
                df['LT'] = longTrade
                shortTrade = False
                df['ST'] = shortTrade


        L'idée est dans un premier temps que cette boucle m'indique simplement un True lorsque la courbe croise l'axe 0 (de façon croissante ou décroissante) et qu'elle me retourne False le reste du temps. Je stocke toutes ces données dans une grande liste d'où les "df" de partout.

        J'ai clairement une erreur quelque part car sur 16000 points, l'algo ne me retourne que des False ... o_O

        Voici un apercu de la liste que me retourne la boucle. On voit clairement que la courbe croise l'axe 0 a 4 reprises.

        • Partager sur Facebook
        • Partager sur Twitter
          24 mars 2022 à 6:12:20

          As-tu vraiment fait un copier-coller de ton code? La ligne suivante:
          for i in range(1, len(df['ROC']+2)):
          donnera une erreur. Je m'attend à:
          for i in range(1, len(df['ROC'])+2):   # Le +2 est hors du len()
          Note que j'ai mis +2 dans mon forcar j'ai un intervalle de range().
          Tu auras probablement un IndexError parce que tu iras au-delà de la fin de ta liste.
          Ensuite:
                  longTrade =True
                  df['LT'] = longTrade
          As-tu besoin de ces variables longtTrade et shortTrade?. Tu peux mettre directement True ou False dans ces positions.
          df['LT"] est supposé être une liste? Parce que là tu la détruit avec une seule valeur True ou False.
          Si c'est vraiment une liste, où vas-tu mettre le True ou False? df['LT'][i-1] ou df['LT'][i]?
          Je mettrais False partout au départ et je mettrais True sur les deux positions de transition quand je les trouve.
          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            24 mars 2022 à 11:16:10

            Comme l'indique PierrotLeFou il manque l'indice i pour les listes df['LT'] et df['ST']
            • Partager sur Facebook
            • Partager sur Twitter
              24 mars 2022 à 16:24:40

              Oui c'est vraiment un copier/coller de mon code. Je travaille avec google colab, ce qui pourrait expliquer que ça soit plus souple que la console sur les erreurs.

              Donc j'ai enlevé le +2 dans le range car effectivement il ne me sert a rien dans mon cas et j'ai rajoutée les [i].

              J'en arrive au code suivant :

              for i in range(1, len(df['ROC'])):
                  if df['ROC'][i-1] < 0 and df['ROC'][i] > 0:
                      df['LT'][i] = True
                  elif df['ROC'][i-1] > 0 and df['ROC'][i] < 0:
                      df['ST'][i] = True
                  else:
                      df['LT'][i] = False
                      df['ST'][i] = False

              Qui me ressort une erreur à cause du [i] sur mes df['LT'] et ST

              Voici l'erreur en question :

              ---------------------------------------------------------------------------
              
              KeyError                                  Traceback (most recent call last)
              
              /usr/local/lib/python3.7/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
                 3360             try:
              -> 3361                 return self._engine.get_loc(casted_key)
                 3362             except KeyError as err:
              
              4 frames
              
              /usr/local/lib/python3.7/dist-packages/pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()
              
              /usr/local/lib/python3.7/dist-packages/pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()
              
              pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()
              
              pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.PyObjectHashTable.get_item()
              
              KeyError: 'LT'
              
              
              The above exception was the direct cause of the following exception:
              
              KeyError                                  Traceback (most recent call last)
              
              <ipython-input-9-9e3aa9710039> in <module>()
                   33         df['ST'][i] = True
                   34     else:
              ---> 35         df['LT'][i] = False
                   36         df['ST'][i] = False
                   37 
              
              /usr/local/lib/python3.7/dist-packages/pandas/core/frame.py in __getitem__(self, key)
                 3456             if self.columns.nlevels > 1:
                 3457                 return self._getitem_multilevel(key)
              -> 3458             indexer = self.columns.get_loc(key)
                 3459             if is_integer(indexer):
                 3460                 indexer = [indexer]
              
              /usr/local/lib/python3.7/dist-packages/pandas/core/indexes/base.py in get_loc(self, key, method, tolerance)
                 3361                 return self._engine.get_loc(casted_key)
                 3362             except KeyError as err:
              -> 3363                 raise KeyError(key) from err
                 3364 
                 3365         if is_scalar(key) and isna(key) and not self.hasnans:
              
              KeyError: 'LT'


              EDIT: quand je remplace mes df LT et St par de simples variables (string) la boucle semble bien fonctionner. L'utilisation des listes me pose vraiment des problèmes...

              -
              Edité par Maykeul 24 mars 2022 à 16:37:33

              • Partager sur Facebook
              • Partager sur Twitter
                24 mars 2022 à 16:40:30

                comment tu créés/récupères ton tableau et en particulier la colonne 'LT' ? (il nous manque cette partie du code)
                • Partager sur Facebook
                • Partager sur Twitter
                  24 mars 2022 à 16:47:57

                  Comment peux-tu dire que c'est False partout si tu n'as pas de liste?
                  Comme l'a dit umfred, peux-tu nous donner le code qui génère df['LT'] et df['ST']
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Le Tout est souvent plus grand que la somme de ses parties.

                    24 mars 2022 à 21:01:16

                    Justement, j'essaye de générer les colonnes LT et ST moi même à partir du résultat. Vu vos réponses, j'en déduit que je m'y prend mal :-°.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      25 mars 2022 à 0:45:52

                      Et si tu faisais:
                      df['LT'] = [False for _ in range(len(df['ROC']))]
                      df['ST'] = [False for _ in range(len(df['ROC']))]
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Le Tout est souvent plus grand que la somme de ses parties.

                        25 mars 2022 à 5:08:16

                        Ah yes ! Oui il fallait définir LT et ST en amont avant de vouloir remplacer les termes à l'intérieur ><. Merci à vous deux en tout cas !

                        • Partager sur Facebook
                        • Partager sur Twitter
                          25 mars 2022 à 17:50:53

                          Je me trompe peut être mais juste une question, pourquoi ne pas reproduire un traitement mathématique au lieu de boucler sur toutes les valeurs, surtout que la précision va impacter le code autant sur les résultats que sur la performance.  C'est quel genre de projet, juste scolaire ou à visée scientifique ?


                          Après c'est sûr que ça sera pas le même algorithme par contre.


                          Après c'est aussi pour satisfaire ma curiosité que je pose la question.

                          -
                          Edité par Daerlnaxe 25 mars 2022 à 17:53:38

                          • Partager sur Facebook
                          • Partager sur Twitter
                            25 mars 2022 à 18:03:23

                            là, on connait les points de la courbe, pas la fonction qui génère la courbe, donc pour l'approche mathématique (si je comprends le sens que tu lui donnes) il faudrait faire une regréssion pour trouver l'équation de la courbe et ensuite, trouver les interceptions mathématiquement.

                            Sinon, je reprenais la question du début, là la 2nde "courbe" est l'axe 0, mais il faudrait si c'est pour comparer 2 courbes, comparer avec les données de celles-ci au même moment et non pas avec 0 (ou le signe de l'écart entre les 2 courbes)

                            • Partager sur Facebook
                            • Partager sur Twitter
                              25 mars 2022 à 18:23:06

                              Mhh ok "sorte de sinusoïde" ... Je présume que ça passe pas non plus en décomposition de Fourrier ? C'est vraiment du signal bâtard ? J'ai plus regardé les courbes c'est pour ça que je bloquais, je comprends mieux. Merci pour la réponse.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                25 mars 2022 à 21:18:36

                                Salut, pour répondre plus en détail Daerlnaxe, c'est un projet parascolaire. J'étudie en ce moment la finance et donc je cherche a déterminer via un programme, le déclenchement de certaines conditions.

                                En gros, en trading on utilise beaucoup d'indicateurs de tendance pour déterminer grossièrement si un cours aura tendance a baisser ou à augmenter. Ma courbe sinusoidale est donc "bâtarde" car randomisée. Il s'agit d'un indicateur qui oscille entre 1 et - 1 et qui croise régulièrement l'axe des abscisses. Mon programme devra juste m'indiquer lorsque que certains indicateurs sont "activés" (càd qu'ils atteignent une valeur cible)

                                Il n'y a donc aucune fonction mathématique derrière.

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  25 mars 2022 à 23:52:28

                                  J'espère que le mot que j'ai employé ne t'a pas choqué, le mot me vient plus maintenant "quelconque" aurait été plus approprié, c'est juste que j'ai étudié la physique électrique si tu veux donc j'ai plus en effet l'habitude de signaux propres ou de travailler en décomposant la courbe, même si je sais que même dans mon domaine on peut aussi se retrouver avec des courbes de ce type. Au début je pensais ceci dit que c'était de la physique quand j'ai regardé les courbes, ça nous arrive de faire varier la pulsation d'un signal en gardant un autre en référence. Voilà désolé pour l'interruption, j'étais curieux.
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    26 mars 2022 à 2:42:31

                                    Pas de problème avec la définition d'une courbe bâtarde :lol:
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Trouver les intersections de deux courbes

                                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                    • Editeur
                                    • Markdown