قسمت اول
هدف از این نوشته، آموزش جولیا نیست، برای این کار هم کتابها و ویدیوهای آموزشی به قدر کفایت هست و هم افراد شایستهتری. هدف، تنها نمایشی کاربردی برای آشنایی است که شاید به دوستی ختم شود.
قبل از پیشتر رفتن، کمی کد قبلی را مرور کنیم
using HTTP
using Inflate
#http://www.tsetmc.com/Loader.aspx?ParTree=151311&i=46741025610365786
namad_id = "46741025610365786"
url = "http://www.tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=$namad_id"
response = HTTP.get(url)
csv_data = String(Inflate.inflate_gzip(response.body))
خط اول از پکیج HTTP برای دریافت اطلاعات از اینترنت استفاده میکند. یکی از نقاط قوت زبانهای برنامهنویسی جدید مدیریت وابستگیها یا dependency برنامه برای اجرا با کمک Package Manager است. برنامهها ممکن است برای اجرا به یک یا چند بسته یا کتابخانه فراتٰر از چیزی که همراه نسخه اصلی زبان ارایه شده است، نیاز داشته باشند. جولیا یک مدیر پکیج داخلی هوشمند دارد و اگر نصب پکیج به پکیجهای دیگر وابسته باشد کارهای لازم برای نصب نسخه مناسب را انجام میدهد.
از پکیج HTTP در خط response = HTTP.get(url) برای دریافت فایل اطلاعات سهام از آدرس url داده شده استفاده میکنیم.
خط دوم هم به جولیا میگوید که از پکیج Inflate استفاده کند. این پکیج برای فشردهسازی و بازکردن اطلاعات فشرده شده استفاده میشود. اطلاعاتی که سایت بورس tsetmc به ما میدهد فایل csv فشرده با فرمت gz است. قبل از اینکه بتوان از این اطلاعات استفاده کرد باید از حالت فشرده خارج شود.
خط سوم که با علامت # آغاز شده خط توضیح یا comment است. بود و نبود این خط تاثیری در عملکرد برنامه ندارد و فقط برای مثالی از استفاده از کامنت در جولیا و البته یادآوری URL اصلی برای دانلود در برنامه گنجانده شده است.
در خط چهارم
namad_id = "46741025610365786"
یک متغیر به اسم namad_id شناسه نماد تعریف کردیم از نوع رشته حرفی یا string. اگر بخواهیم اطلاعات نماد دیگری را دریافت کنیم کافیست مقدار این متغیر عوض شود. اگر دقت کرده باشید در قسمت اول این متغیر مقدار دیگری داشت که شناسه نماد شرکت زامیاد یا خزامیا بود و در قسمت دوم به نماد گروه سرمایه گذاری میراث فرهنگی (سمگا) تغییرش دادهایم.
خط پنجم
url = "http://www.tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=$namad_id"
یک متغیر دیگر به نام url تعریف میشود که آدرس URL اطلاعات معاملات روزانه نماد سمگا است. چرا مستقیما آدرس کامل
http://www.tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=46741025610365786
را ننوشتیم؟ چون میخواستیم نحوه جایگذاری متغیرها داخل رشته حرفی string یا String interpolation را نشان بدهیم. علامت دلار $ قبل از متغیر namad_id یعنی مقدار آن در داخل رشته جایگزین شود.
در خط ششم response = HTTP.get(url) درخواست دریافت اطلاعات داده میشود و پاسخ سایت در متغیری به نام response ذخیره میشود. اطلاعات دریافتی از روی URL خواسته شده همانطور که گفتیم فایل csv فشرده بصورت gz است. برای استفاده باید gz باز شود. البته response جواب کامل برگشتی از سایت هست شامل کد وضعیت و متن جواب و اطلاعات هدر. متن جواب در فیلد body ذخیره شده است.
در خط هفتم،
csv_data = String(Inflate.inflate_gzip(response.body))
گفتیم متن جواب سایت در فیلد body هست و باید آن را decompress، نافشرده یا باز کنیم. برای اینکار تابع inflate_gzip را از پکیج Inflate صدا میزنیم و جواب حاصل که باینری هست را تبدیل به رشته حرفی میکنیم و در متغیر csv_data ذخیره میکنیم.
حاصل این کار خروجی به فرمت csv است. مانند زیر
<TICKER>,<DTYYYYMMDD>,<FIRST>,<HIGH>,<LOW>,<CLOSE>,<VALUE>,<VOL>,<OPENINT>,<PER>,<OPEN>,<LAST> Cultur.Herit..Inv.,20190924,8010.00,8270.00,7867.00,8070.00,213100775837,26407181,6296,D,7967.00,7998.00 Cultur.Herit..Inv.,20190923,7800.00,8150.00,7751.00,7967.00,189504835007,23784730,6167,D,7749.00,7896.00 Cultur.Herit..Inv.,20190922,7860.00,7935.00,7600.00,7749.00,175737091105,22677518,5857,D,7716.00,7740.00
حالا این اطلاعات csv را لود کرده و از ۱۲ فیلد اطلاعاتی اطلاعات قیمت پایانی هر روز را استخراج میکنیم.
فقط دقت کنید که اسامی ستونها در اطلاعاتی که توسط سایت بورس ارایه میشود بصورت زیر است.
<TICKER>,<DTYYYYMMDD>,<FIRST>,<HIGH>,<LOW>,<CLOSE>...<OPEN>,<LAST>
اسامی ستونها در بین علامتهای <> قرار داده شدهاند. جلوتر توضیح خواهیم داد که کمی این نحوه نامگذاری را تبدیل خواهیم کرد تا کد خواناتر شود.
برای کار با فایلها و اطلاعات csv پکیجهای متنوعی داریم از پکیج TableReader و متد readcsv استفاده خواهیم کرد.
using HTTP
using Inflate
using TableReader
#http://www.tsetmc.com/Loader.aspx?ParTree=151311&i=46741025610365786
namad_id = "46741025610365786"
url = "http://www.tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=$namad_id"
response = HTTP.get(url)
csv_data = String(Inflate.inflate_gzip(response.body))
csv = readcsv(IOBuffer(csv_data),normalizenames=true)
close_values = csv[:_CLOSE_]
توضیح خط آخر اینکه بیشتر متدهای کار با csv پیشفرضشان این است که اطلاعات را از فایل csv میخوانند. ما اطلاعات را در حافظه و در متغیر csv_data ذخیره کردهایم. با متد IOBuffer این stream داخل حافظه را تبدیل به آرایه مناسب برای تابع readcsv میکنیم. پارامتر normalizenames که مقدار true گرفته باعث تبدیل اسامی ستونها میشود مثلا ستون <CLOSE> تبدیل میشود به _CLOSE_
خروجی به صورت زیر نمایش داده خواهد شد.
حالا میتوانیم به اطلاعات تکتک سطر و ستونها دسترسی داشته باشیم مثلا دستور size(csv) تعداد سطر و ستونهای اطلاعات را نشان میدهد. خروجی دستور
(1522, 12)
یعنی ۱۲ ستون و ۱۵۲۲ سطر
دستور names(csv) اسامی ستونها را نشان میدهد
12-element Array{Symbol,1}: :_TICKER_ :_DTYYYYMMDD_ :_FIRST_ :_HIGH_ :_LOW_ :_CLOSE_ :_VALUE_ :_VOL_ :_OPENINT_ :_PER_ :_OPEN_ :_LAST_
حالا میتوانیم به ستون ششم یعنی مقادیر CLOSE یا پایانی روز دسترسی پیدا کنیم
close_values = csv[:_CLOSE_]
البته میتوانستیم در عوض خط بالا بنویسیم
close_values = csv[:6]
تا ستون ششم اطلاعات که همان مقدار CLOSE یا قیمت پایانی روز معاملاتی است را بدست بیاوریم. حالا دلیل تبدیل نامگذاری ستونها را بهتر متوجه میشویم. close_values = csv[:_CLOSE_] خوانتر و قابل فهمتر است.
یک نکته هم در مورد نحوه شمردن آرایه در جولیا متوجه میشویم. جولیا بر خلاف بیشتر زبانهای برنامهنویسی اندیس آرایهها را از ۱ میشمارد و مانند زبانهای C/Java و .. نیست که شمارش آرایه را از صفر شروع میکنند.
خروجی دستور close_values = csv[:_CLOSE_] مانند زیر است
1522-element Array{Float64,1}: 8070.0 7967.0 7749.0
⋮ 1755.0 1672.0 1593.0
برای ترسیم نمودار قیمت پایانی از پکیج Plots استفاده کرد.
یکی از مزایای جولیا امکان همکاری و استفاده از زبانهای دیگر مانند پایتون و R و ... است. در واقع جولیا را میتوان مکمل و نه رقیب این زبانها دانست. مثلا جولیا میتواند از پکیجهای پایتون هم استفاده کند. مثلا میتوانیم پکیج PyPlot پایتون را هم نصب کرد.
برای استفاده از پکیج Plots مینویسیم
using Plots
برای ترسیم نمودار از تابع plot استفاده میکنیم. چون مقادیر Close یا قیمت پایانی، از تاریخ روز به اول هستند، قبل از صدا زدن plot باید ترتیب تاریخی مقادیر Close معکوس شود.
plot(reverse(close_values),label="Close", lw=2)
با reverse(close_values) ترتیب آرایه معکوس میشود. lw مخفف Line Width یا عرض خط است
نتیجه دستور بالا ترسیم نمودار زیر است
در قسمت بعد سراغ محاسبه اندیکاتور یا اوسیلاتور CCI یا Commodity Channel Index خواهیم رفت.