اذهب إلى المحتوى
  • 0

حساب المتوسط المتحرك moving average فيnumpy؟

Fahmy Mostafa

السؤال

Recommended Posts

  • 2

 قبل كل شيء المتوسط المتحرك في علم الإحصاء، المتوسط المتحرك (MA) هو عملية حسابية تُستخدم لتحليل نقاط البيانات (العينات) عن طريق إنشاء سلسلة من المتوسطات لمجموعات فرعية مختلفة من مجموعة البيانات الكاملة. ويستخدم في عالم الأموال، حيث أن المتوسط المتحرك (MA) هو مؤشر سهم يستخدم بشكل شائع في التحليل التقني. والسبب في حساب المتوسط المتحرك للسهم هو المساعدة في تسهيل بيانات السعر عن طريق إنشاء متوسط سعر محدث باستمرار. ومن خلال حساب المتوسط المتحرك ، يتم تخفيف آثار التقلبات العشوائية قصيرة الأجل على سعر السهم خلال إطار زمني محدد. لن أخوض في تفاصيله الممتعة أكثر. له نوعان، Simple Moving Average:
أبسط شكل من أشكال المتوسط المتحرك ، والمعروف باسم المتوسط المتحرك البسيط (SMA) ، يتم حسابه بأخذ المتوسط الحسابي لمجموعة معينة من القيم. بمعنى آخر ، يتم جمع مجموعة من الأرقام - أو الأسعار في المجال المالي - معًا ثم تقسيمها على عدد الأسعار في المجموعة. (وهو النوع الأكثر استخداماً)

SMA=(A1+A2+..+AN)/n
A:nهي المتوسط في الفترة 
N: عدد الفترات الزمنية

 Exponential Moving Average (EMA):
يعطي وزناً أكبر للأسعار الحديثة في محاولة لجعله أكثر استجابة للمعلومات الجديدة. لحساب المتوسط المتحرك الأسي:

EMAt=[Vt×S/(1+d)]+EMAy×[1−S/(1+d)]
EMAt: لليوم
Vt: هي القيمة لليوم
EMAy: للأمس
S: التنعيم
d:عدد الأيام

الآن كيف نطبقه في بايثون:
1.الطريقة الأولى: قم بإنشاء قائمة فارغة تحتوي على المتوسطات المتحركة. قم بالمرور على القائمة الأصلية باستخدام حلقة while. في كل تكرار ، استخدم فهرسة القائمة للحصول على النافذة الحالية. استخدم sum(iterable) / w_s ثم أضف هذه النتيجة إلى قائمة المتوسطات المتحركة:

li = [6, 7, 10, 12]
# حجم النافذة
w_s = 3
i = 0
moving_averages = []
j=len(li) - w_s + 1
while i < j:
    this_window = li[i : i + w_s]
    window_avg = sum(this_window) / w_s
    moving_averages.append(window_avg)
    i += 1
print(moving_averages)

2. من أجل القوائم الكبيرة تقدم باندا طريقة فعالة هي pandas.Series(data) لتحويل القائمة إلى pandas.Series object. ثم استدعي pandas.Series.rolling (window_size) للحصول على كائن يحتوي كل نافذة، ثم استدعي pandas.Series.mean لإيجاد المتوسط لكل نافذة :

li = [6, 7, 10, 12]
w_s = 3
pd = pd.Series(li)
windows = pd.rolling(w_s)
moving_averages = windows.mean()
#  pandas.Series.tolist() لتحويلها لقائمة
moving_averages_list = moving_averages.tolist()
# حذف القيم Nan
w = moving_averages_list[w_s - 1:]
print(w)

3.باستخدام نمباي:

4. والطريقة الأكثر سرعة هي استخدام uniform_filter1d من scipy فهي أسرع بنحو 50 مرة من np.convolve و 2-5 مرات من cumsum :

from scipy.ndimage.filters import uniform_filter1d
import numpy
N = 1000
x = numpy.random.random(100000)
y = uniform_filter1d(x, size=N)

لاحظ:

%timeit y1 = np.convolve(x, np.ones((N,))/N, mode='same')
100 loops, best of 3: 9.28 ms per loop
%timeit y2 = uniform_filter1d(x, size=N)
10000 loops, best of 3: 191 µs per loop

إليك التحقيقات الثلاثة التي ذكرتها:

import numpy as np
import scipy.ndimage.filters as ndif
from __future__ import division
#cumsum استخدام 
def running_mean_cumsum(x, N):
    cumsum = np.cumsum(np.insert(x, 0, 0))
    return (cumsum[N:] - cumsum[:-N]) / float(N)
#convolve استخدام 
def running_mean_convolve(x, N):
    return np.convolve(x, np.ones(N) / float(N), 'valid')
#uniform_filter1d وأخيراً 
def running_mean_uniform_filter1d(x, N):
    return ndif.uniform_filter1d(x, N, mode='constant', origin=-(N//2))[:-(N-1)]

 

تم التعديل في بواسطة Ali Haidar Ahmad
رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

يمكنك حساب المتوسط المتحرك فيnumpy باستخدام np.convolve. حيث يمكننا الاستفادة من الطريقة التي يتم بها حساب الالتواء المنفصل أو ما يعرف ب discrete convolution واستخدامه لإرجاع rolling mean. يمكن القيام بذلك عن طريق استخدام np.ones بطول معين,بداية سوف نقوم بانشاء الدالة المسؤولة عن حساب moving average 

def moving_average(x, w):
    return np.convolve(x, np.ones(w), 'valid') / w

والآن نستطيع استخدام هذه الدالة لحساب moving average كالتالي

x = np.array([5,3,8,10,2,1,5,1,0,2])

بالنسبة ل moving average مع طول يساوي 2 فسوف يكون شكل الكود كالتالي

moving_average(x, 2)

وسوف يكون الناتج كالتالي

array([4. , 5.5, 9. , 6. , 1.5, 3. , 3. , 0.5, 1. ])

لنفترض أن الطول كان يساوي 4 فسوف يكون الناتج كالتالي

moving_average(x, 4)

# array([6.5 , 5.75, 5.25, 4.5 , 2.25, 1.75, 2.  ])

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

يمكنك استخدام الدالة التالية لحساب ال moving average، و لكنها ستكون أبطأ بعض الشئ من الحلول الخاصة ب numpy 



mylist = [1, 2, 3, 4, 5, 6, 7]
N = 3
cumsum, moving_aves = [0], []

for i, x in enumerate(mylist, 1):
    cumsum.append(cumsum[i-1] + x)
    if i>=N:
        moving_ave = (cumsum[i] - cumsum[i-N])/N
        #can do stuff with moving_ave here
        moving_aves.append(moving_ave)

و يمكنك استخدام الطريقة التالية أيضًا (تستخدم Convolution):

def running_mean(x, N):
    cumsum = numpy.cumsum(numpy.insert(x, 0, 0)) 
    return (cumsum[N:] - cumsum[:-N]) / float(N)

و لكن هذه الطريقة يظهر بها خطأ متعلق بال precision الخاصة بال floating point 

أو يمكنك استخدام scipy.ndimage.filters.uniform_filter1d فهي طريقة أسرع 50 مرة من np.convolve و لا يظهر معها خطأ متعلق بال precision الخاصة بال floating point :

import numpy as np
from scipy.ndimage.filters import uniform_filter1d
N = 1000
x = np.random.random(100000)
y = uniform_filter1d(x, size=N)

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...