الگوسهام | AlgoSaham
کل ---%---

آموزش فیلترنویسی با پایتون

از اولین شرط روی تابلو تا تحلیل تاریخچه و انتخاب نمادها از کل بازار؛ همراه با نسخهٔ پایتون هر ۲۴ راهنمای فیلترنویسی الگوسهام.

پیش از نوشتن اولین فیلتر

کد پایتون روی سرور و روی یک تصویر از داده‌های بازار اجرا می‌شود. تاریخچه‌ها در هر اجرا آماده‌اند و نیازی به بارگذاری دستی ندارند. برای تمرین، ویرایشگر پایتون را باز کنید و حالت اجرا را مطابق مثال انتخاب کنید.

دو حالت اجرا؛ کدام را انتخاب کنیم؟

در «اجرا به ازای هر نماد»، برنامه برای هر نماد جداگانه اجرا می‌شود. آخرین عبارت در سطح اصلی برنامه، شرط انتخاب است؛ آن را در خط آخر بنویسید. این حالت برای شرط‌های مستقل روی قیمت، حجم یا تاریخچهٔ هر نماد مناسب است. نتیجه بر اساس حجم امروز نزولی مرتب می‌شود.
# اجرا به ازای هر نماد
pl > py and tvol > 1_000_000
اگر خط آخر فقط انتساب باشد یا هیچ عبارت پایانی نداشته باشید، هر نمادی که کدش بدون خطا اجرا شود انتخاب می‌شود. در سطح اصلی برنامه return ننویسید. خطا در این حالت همان نماد را کنار می‌گذارد.
در «اجرا روی کل بازار»، برنامه یک بار اجرا می‌شود. اعضای market شیء نمادند و توکن‌ها را با پیشوند s. می‌خوانید. برای مقایسه، رتبه‌بندی یا انتخاب تعداد مشخصی نماد از این حالت استفاده کنید. در پایان result باید مجموعه‌ای از همین نمادها یا کدهای آن‌ها باشد؛ ترتیب و تکرارها حفظ می‌شود. خطای مهارنشده کل اجرا را ناموفق می‌کند.
result = []
for s in market:
    if s.pl > s.py and s.tvol > 1_000_000:
        result.append(s)
# سه نماد پرحجم از میان انتخاب‌ها
result = sorted(result, key=lambda s: s.tvol, reverse=True)[:3]

توکن‌ها، row و ct

نام توکن‌ها متغیر ساده است: pl آخرین قیمت، pc پایانی، py قیمت دیروز، tvol حجم، tval ارزش، tno تعداد معاملات و bvol حجم مبنا. l18 نام کوتاه و ins کد نماد است. پرانتزهای زبان فیلتر جاوااسکریپت لازم نیست.
row دیکشنری ردیف خام بازار است و ct همان دیکشنری است؛ دادهٔ حقیقی و حقوقی را با کلید رشته‌ای می‌خوانیم. در حالت کل بازار از s.row و s.ct استفاده کنید. تقسیم بر صفر را پیش از محاسبه کنترل کنید.
# اجرا به ازای هر نماد
buyers = ct["Buy_CountI"]
cfield0 = pc * ct["Buy_I_Volume"] / buyers if buyers > 0 else 0
print(row["InsCode"], l18)
cfield0 > 100_000_000

تاریخچه: روزها، هفته‌ها و دادهٔ حقیقی/حقوقی

ih تاریخچهٔ روزانه، it روزانهٔ تعدیل‌شده، wh هفتگی، wt هفتگی تعدیل‌شده و ic تاریخچهٔ حقیقی/حقوقی است. هر روز یک دیکشنری با نام فیلدهای اصلی، مثل PClosing یا QTotTran5J است.
اندیس صفر جدیدترین روز موجود است؛ طی جلسه معمولاً آخرین روز تکمیل‌شده است و پس از بازسازی می‌تواند امروز باشد. روز ناموجود، اندیس خارج از محدوده و اندیس منفی None می‌دهند؛ اندیس منفی به معنای آخرین روز نیست. len(ih) طول تاریخچه را می‌دهد و برش‌هایی مثل ih[:10] فهرست می‌سازند که ممکن است داخلش None باشد. دیکشنری هر خواندن کپی تازه است؛ برای محاسبات قابل تغییر، یک فهرست محلی بسازید.
# اجرا به ازای هر نماد
bars = [bar for bar in ih[:10] if bar is not None]
volumes = [bar["QTotTran5J"] for bar in bars
           if math.isfinite(bar["QTotTran5J"])]
avg = statistics.mean(volumes) if len(volumes) >= 5 else 0
tvol > 2 * avg and avg > 0

ستون‌های سفارشی و عنوان آن‌ها

ده ستون cfield0 تا cfield9 در شروع هر نماد None هستند. با انتساب، مقدار آن‌ها در نتیجه نمایش داده می‌شود؛ در حالت کل بازار مقدار را روی خود نماد بنویسید. عنوان ستون‌ها را در بخش «ستون‌های سفارشی» ویرایشگر تعیین کنید؛ عنوان در کد با cfield0_title تعریف نمی‌شود. مثلاً برای این مثال عنوان «نسبت حجم به مبنا» را انتخاب کنید.
# اجرا روی کل بازار
result = []
for s in market:
    if s.bvol > 0:
        s.cfield0 = s.tvol / s.bvol
        if s.cfield0 > 2:
            result.append(s)

خلاصهٔ بازار با gfield و خروجی print

gfield0 تا gfield9 در شروع هر اجرا صفر و عنوان‌هایشان خالی‌اند. تنها فیلد دارای عنوان نمایش داده می‌شود. در حالت نمادی، مقدار بین نمادها، حتی نماد کنارگذاشته‌شده، حفظ می‌شود؛ در حالت کل بازار یک بار مقدار و عنوان را تعیین می‌کنید.
# اجرا به ازای هر نماد
gfield0_title = "تعداد صف خرید"
matched = pd1 == tmax and qo1 == 0
if matched:
    gfield0 += 1
    print(l18, "صف خرید")
matched
print() متن را در خروجی اجرای فیلتر نشان می‌دهد و شرط انتخاب نماد نیست. برای عیب‌یابی مقدارهای میانی را چاپ کنید، نه کل تاریخچهٔ بازار.

ماژول‌های آماده

math، نامپای با نام np، پانداس با نام pd و statistics بدون import در دسترس‌اند. تاریخچه DataFrame نیست؛ ابتدا روزهای None را حذف و سپس آن را تبدیل کنید.
frame = pd.DataFrame([bar for bar in ih if bar is not None])
print(frame.head(3))
len(frame) >= 20

تفاوت‌های مهم با زبان جاوااسکریپت

به جای && و || و ! از and، or و not استفاده کنید؛ مقدارهای منطقی True/False و مقدار خالی None هستند. تورفتگی جای آکولاد را می‌گیرد. برای تاریخچه ih[0]["PClosing"] می‌نویسیم و برای طول، len()؛ Math.round و parseFloat تابع آمادهٔ پایتون نیستند.
round پایتون نیم‌ها را به عدد زوج گرد می‌کند، اما Math.round آن‌ها را به سمت مثبت می‌برد. تقسیم بر صفر در پایتون خطاست؛ در جاوااسکریپت Infinity یا NaN تولید می‌کند. NaN در مقایسهٔ عددی شرط را برقرار نمی‌کند، ولی bool(NaN) در پایتون True است. رشته و عدد نیز خودکار مثل جاوااسکریپت تبدیل نمی‌شوند. در راهنماها تقسیم‌ها پیش از اجرا بررسی می‌شوند و عددهای اعشاری با round(value, 2) نمایش داده می‌شوند. برای گرد کردن نیم‌ها به سمت بالا در ستون‌های عدد صحیح از math.floor(value + 0.5) استفاده می‌کنیم؛ ستون‌های مک‌دی نیز مقدار عددی دارند.

محدودیت‌های اجرا و نتیجه

هر اجرا حداکثر ۲۰ ثانیه زمان و محدودیت پردازنده و حافظه دارد. خروجی print برای کل اجرا به ۲۰٬۰۰۰ کاراکتر محدود است؛ پاسخ بیش از ۱۶ مگابایت پذیرفته نمی‌شود، نتیجه حداکثر ۱۰۰۰ ردیف دارد و مقدار متنی هر ستون تا ۳۰۰ کاراکتر نگه داشته می‌شود. عددهای نامتناهی و NaN در ستون نتیجه به مقدار خالی تبدیل می‌شوند. از حلقه‌های بی‌پایان و چاپ آرایه‌های بزرگ پرهیز کنید.

۲۴ راهنمای کاربردی با کد پایتون