تجسم نمودار نمایندگی تجاری Bitcoin RL با استفاده از Matplotlib و Python #2

ساخت وبلاگ

در این بخش ، ما قصد داریم کد نوشته شده در آموزش قبلی خود را برای ارائه تجسم ربات تجارت Bitcoin RL با استفاده از Matplotlib و Python گسترش دهیم

ساق پامنتشر شده در 14 دسامبر 2020 ارسال به فیس بوک! ارسال به توییتر ارسال به Google+! از طریق LinkedIn به اشتراک بگذارید از طریق ایمیل به اشتراک بگذارید ارسال به Reddit از طریق WhatsApp به اشتراک بگذارید ارسال به تلگرام مانند آموزش باید مانند 0 وارد شوید

پیشرفته ترین نقشه های علوم داده ای که تاکنون دیده اید! همراه با هزاران منبع یادگیری رایگان و ادغام chatgpt! https://aigents. co/lea/roadmaps/intro

در این بخش ، کدی را که در آموزش قبلی من نوشته شده است برای تجسم ربات تجارت Bitcoin RL با استفاده از Matplotlib و Python گسترش خواهیم داد. اگر آموزش قبلی من را نخوانده اید و با کدی که نوشتم آشنا نیستید ، توصیه می کنم قبل از خواندن این آموزش بیشتر بخوانید.

اگر با کتابخانه Matplotlib Python ناآشنا هستید ، نگران نباشید. من به مرحله به مرحله کد می روم ، بنابراین می توانید تجسم سفارشی خود را ایجاد کنید یا با توجه به نیاز خود ، معدن را اصلاح کنید. اگر نمی توانید همه چیز را درک کنید ، این کد آموزش همیشه در مخزن GitHub من موجود است.

قبل از حرکت به جلو ، پیش نمایش کوتاهی از آنچه می خواهیم در این آموزش ایجاد کنیم به شما نشان خواهم داد:

شروع کنیم! در نگاه اول ، ممکن است کاملاً پیچیده به نظر برسد ، اما در واقع ، این کار سختی نیست. این فقط چند پارامتر است که در هر مرحله از محیط با برخی از اطلاعات ضروری با کمک Matplotlib که قبلاً عملکردی نوشته شده است ، به روز می شوند.

تجسم ربات تجارت بیت کوین

ما یک روش رندر ساده را با استفاده از بیانیه های چاپی نوشتیم تا ارزش خالص عامل را در آخرین آموزش خود نشان دهیم. من می توانستم معیارهای اساسی دیگری را اضافه کنم ، اما آنها را به این آموزش واگذار کردم. بنابراین ، بیایید در صورت لزوم ، نوشتن آن منطق را به یک پرونده روش جدید به نام uTils. py برای ذخیره معیارهای معاملاتی جلسه در یک پرونده شروع کنیم. من با ایجاد یک تابع ساده به نام write_to_file () شروع می کنم ، و ما هر آنچه را که برای این عملکرد به یک فایل متنی ارسال می شود وارد می کنیم:

وارد کردن سیستم عامل def write_to_file (تاریخ ، net_worth ، نام پرونده = '<>. txt'. Format (dateTime. Now (). strftime ("٪ y- ٪ m- ٪ d ٪ h: ٪ m: ٪ s")))): برای من در net_worth: تاریخ += "<>". format (i) #print (تاریخ) اگر نه os. path. exists ('logs'): os. makedirs ('logs') پرونده = باز (" logs/"+filename ،" a+") پرونده. write(تاریخ+" n") file. close ()

اکنون به سادگی از کد اصلی ما ، آن را از طریق UTILS واردات WRITE_TO_FILE وارد می کنم. من ترجیح می دهم این عملکرد را یک تابع مرحله بنامم ، درست بعد از اینکه خود را انجام می دهیم. به این پرونده ، اما کافی بود که اولین شماره را با کد من پیدا کنم.

من متوجه شدم که وقتی ربات من یک عملیات خرید را انجام می دهد ، تعادل من صفر نیست ، اما نزدیک به صفر است ، به طور دقیق ت ر-1. 1368683772161603 E-13. بنابراین به جای اندازه گیری اگر تعادل من بیش از 0 باشد ، فکر کردم بهتر است اندازه گیری شود که تعادل فعلی بیش از 1 ٪ از کل تعادل اولیه من باشد:

elif action == 1 and self.balance>self. initial_balance/100: اما این آموزش مربوط به اشکالات و پیشرفت های دیگر نیست. بیایید به سمت ایجاد روش جدید رندر خود حرکت کنیم. این از کلاس جدید TradingGraph که ما هنوز ننوشته ایم استفاده خواهد کرد. بعد به آن خواهیم رسید. من قصد ندارم کد کامل را در اینجا نشان دهم. من قبل از استفاده از TradingGraph من به شما نشان می دهم که در کد من جدید است:

class CustomEnv: def __init__(self, Render_range = 100): self.Render_range = Render_range # render range in visualization def reset(self): self.visualization = TradingGraph(Render_range=self.Render_range) # init visualization self.trades = deque(maxlen=self.Render_range) # limited orders memory for visualization def step(self, action): Date = self.df.loc[self.current_step, 'Date'] # for visualization High = self.df.loc[self.current_step, 'High'] # for visualization Low = self.df.loc[self.current_step, 'Low'] # for visualization if action == 0: # Hold pass elif action == 1 and self.balance> self.initial_balance/100: self.trades.append() elif action == 2 and self.crypto_held>0: self. trades. append () نوشتن_to_file (تاریخ ، self. orders_history [-1]) # ارائه محیط ارائه def render (خود ، تجسم = نادرست): #print (f'step: ، ارزش خالص: ') اگر تجسم کنید:تاریخ = self. df. loc [self. current_step ، 'date'] باز = self. df. loc [self. current_step ، 'open'] close = self. df. loc [self. current_step ، 'close'] high = =self. df. loc [self. current_step ، 'high'] low = self. df. loc [self. current_step ، 'low'] volume = self. df. loc [self. current_step ، 'volume'] # محیط را ارائه دهیدبه صفحه نمایش خود. visualization. Render (تاریخ ، باز ، بالا ، پایین ، نزدیک ، حجم ، self. net_worth ، self. trades)

در اینجا ، در بالا ، اصلی ترین تغییرات از قسمت آموزش قبلی من است. همانطور که مشاهده می کنید ، در قسمت __init__ ، باید دامنه رندر خود را آغاز کنیم. این بدان معنی است که چند قسمت از تاریخ را دوست داریم ارائه دهیم.

در عملکرد تنظیم مجدد ، ما یک شیء جدید با کلاس TradingGraph خود ایجاد می کنیم. و البته ، ما یک لیست محدود از لیست معاملات را ایجاد می کنیم. ما از این لیست برای قرار دادن کلیه سفارشات (خرید/فروش) استفاده خواهیم کرد که ربات ما انجام می دهد تا بتوانیم آنها را در طرح زیبای خود ترسیم کنیم.

در عملکرد مرحله ، ما نکات اصلی قیمت خود را (تاریخ ، بالا ، پایین) دریافت می کنیم و وقتی ربات ما سفارش می دهد ، این اطلاعات را به عنوان فرهنگ لغت در لیست معاملات خود قرار خواهیم داد.

و آخرین عملکرد اصلاح شده یک رندر است. همانطور که مشاهده می کنید ، می توانیم تجسم را با پارامترهای واقعی/غلط روشن یا خاموش کنیم. در اینجا ما تمام پارامترهای لازم (تاریخ ، باز ، بسته ، زیاد ، کم ، حجم) را می گیریم و به خودی خود. visualization. Render. همچنین ، از آنجا که ما می خواهیم نشان دهیم که چگونه ارزش خالص ما تغییر می کند و ربات ما باعث فروش یا خرید سفارش می شود ، ما پارامترهای self. net_worth و self. trades را به همان عملکرد ارسال خواهیم کرد.

اکنون TradingGraph ما تمام اطلاعات مورد نیاز خود را برای ارائه تاریخچه قیمت بازار و حجم تجارت ، همراه با ارزش خالص نماینده ما و هرگونه معاملات انجام شده در اختیار ما قرار می دهد. بیایید شروع به ارائه تجسم خود کنیم! ابتدا همه کتابخانه های لازم را برای نمودار خود وارد خواهیم کرد ، سپس ما گراف تجاری و روش __init__ آن را تعریف خواهیم کرد. در اینجا جایی است که ما شکل Matplotlib خود را ایجاد خواهیم کرد و هر زیرمجموعه ای را برای ارائه تنظیم می کنیم.

در اینجا من با تعریف سبک و اندازه شکل ، اولین نگاه خود را ایجاد می کنم. اول ، ما برخی از لیست های Deque را تعریف می کنیم ، جایی که ما اطلاعات موقت خود را برای نمودار خود ذخیره خواهیم کرد. همچنین ، من در صورت باز شدن همه توطئه ها را می بندم - این ضروری است که بخواهیم نمودار قسمت دوم را شروع کنیم (عامل تنظیم مجدد و مجدداً هر قسمت را مجدداً تنظیم می کند).

واردات پاندا به عنوان pd از مجموعه واردات واردات matplotlib. pyplot به عنوان plt از mplfinance. original_flavor candlestick_ohlc واردات matplotlib. dates as mpl_dates از dateTime واردات داده های واردات واردات واردات os cv2 به عنوان np class class tradinggraph: # a crrypto tradization tostralplotlotilقیمت های سفارشی را که به زیر آمده است ارائه دهید: # تاریخ ، باز ، بالا ، کم ، نزدیک ، حجم ، NET_WORTH ، معاملات # تماس با هر مرحله def __init __ (خود ، render_range): self. volume = deque (maxlen = render_range) خود. net_worth = deque (maxlen = render_range) self. render_data = deque (maxlen = render_range) self. render_range = render_range # ما از سبک "ggplot" plt. style. use استفاده می کنیم ('ggplot') # همه بسته ها را باز کنید. plt. close ('all') # ویژگی FigSize به ما امکان می دهد عرض و ارتفاع یک شکل را در واحد اینچ خود نشان دهیم. ax1 = plt. subplot2grid ((6،1) ، (0،0) ، Rowspan = 5 ، colspan = 1) # زیرمجموعه پایین را برای حجم ایجاد کنید که خود را به اشتراک می گذارد.) ، (5،0) ، Rowspan = 1 ، colspan = 1 ، sharex = self. ax1) # یک محور جدید برای ارزش خالص ایجاد کنید که محور x خود را با قیمت self. ax3 = self. ax1. twinx () # به اشتراک می گذارد. تاریخ قالب بندی self. date_format = mpl_dates. dateformatter ('٪ d- ٪ m- ٪ y') # self. date_format = mpl_dates. dateformatter ('٪ d- ٪ m- ٪ y') # اضافه کردن لباس ها برای دیدن نمودار آسانتر مشاهده# plt. subplots_adjust (سمت چپ = 0. 07 ، پایین = -0. 1 ، راست = 0. 93 ، بالا = 0. 97 ، wspace = 0 ، hspace = 0) # ما باید لایه های self. ax2. set_xlabel ('date') self. ax1 را تنظیم کنیم. set_ylabel ('price') self. ax3. set_ylabel ('تعادل') # من برای جایگزینی plt. subplots_adjust خود استفاده می کنم.

همانطور که مشاهده می کنید ، ما از روش plt. subplot2grid (.) استفاده می کنیم تا ابتدا یک زیرمجموعه اصلی در بالای شکل خود ایجاد کنیم تا داده های شمعدانی بازار خود را ارائه دهیم ، و سپس برای حجم خود زیر مجموعه دیگری را در زیر آن قرار می دهیم. و آخر ، ما یک محور سوم را با عملکرد Twinx () ایجاد می کنیم ، که به ما امکان می دهد شبکه دیگری را در بالا قرار دهیم که همان محور x را به اشتراک می گذارد. اولین آرگومان عملکرد Subplot2Grid اندازه زیرمجموعه و دوم مکان موجود در شکل است.

معمولاً برخی از نمودارها را با کتابخانه Matplotlib ترسیم می کنیم. بیشتر حاشیه های بزرگ سفید وجود دارد که نمودار ما را کوچکتر می کند ، بنابراین توصیه می شود آنها را حذف کنید. تاکنون از تابع subplot_adjust () استفاده کردم ، اما فهمیدم که tigh_layout () بسیار بهتر است. ما نیازی به اندازه گیری اندازه حاشیه سفید نداریم. همچنین ، این غیر ضروری است ، اما نمودار ما با برچسب های طرفین بسیار بهتر به نظر می رسد ، بنابراین تاریخ ، قیمت ، محور تعادل را تنظیم کردم که در آینده این کار را فراموش نکنند. سرانجام و از همه مهمتر ، ما با استفاده از plt. show () شکل خود را به صفحه نمایش خواهیم داد:

بعد ، بیایید روش رندر خود را بنویسیم. این همه اطلاعات را از مرحله زمانی فعلی به خود اختصاص می دهد و یک نمایش زنده را به صفحه نمایش می دهد. یکی از پیچیده ترین چیزها ارائه نمودار قیمت است. اما خوشبختانه ، برای ساده نگه داشتن امور ، می توانیم از میله های OHCL از کتابخانه MPLFinance که قبلاً وارد کرده ایم استفاده کنیم. اگر قبلاً آن را ندارید ، PIP نصب MPLFinance را بنویسید ، زیرا این بسته ساده ترین راه برای ترسیم نمودارهای شمعدان است.

از عملکرد Date2Num برای اصلاح تاریخ در زمان بندی استفاده می شود ، که در فرآیند ارائه OHCL لازم است. هر مرحله رندر ، داده های OHCL لازم خود را به حافظه DEQUE اضافه می کنیم ، که در طرح ما ارائه می شود. از آنجا که نمودار ما پویا است ، ما باید قبل از تولید یک قاب قبلی را پاک کنیم. پس از انجام این کار ، ما داده های OHCL را می گیریم و نمودار شمعدانی را به زیر مجموعه Self. ax1 می دهیم.

از آنجا که ما همه محورهای خود را در هر قاب پاک می کنیم ، برچسب های ما نیز پاک می شوند ، بنابراین ما آنها را از قسمت __init__ به قسمت ارائه می دهیم. سرانجام و از همه مهمتر ، ما با استفاده از plt. show (بلوک = نادرست) شکل خود را به صفحه نمایش خواهیم داد. اگر فراموش کنید که Block = False را عبور دهید ، فقط اولین قدم ارائه شده را مشاهده خواهید کرد که پس از آن عامل از ادامه کار مسدود خواهد شد. تماس با plt. pause () ضروری است. در غیر این صورت ، قبل از اینکه آخرین قاب در واقع روی صفحه نمایش داده شود ، هر فریم با تماس بعدی برای ارائه ارائه می شود.

تجارت کلاس: def __init __ (خود ، render_range) :.# رندر محیط را به صفحه نمایش ارائه دهید (خود ، تاریخ ، باز ، بالا ، پایین ، نزدیک ، حجم ، NET_WORTH ، Trades): # قبل از افزودن به لیست DEQUE ، نیاز به تبدیل تاریخ به تاریخ قالب ویژه = MPL_DATES. DATE2NUM ([[[[pd. to_datetime (تاریخ)]) [0] self. render_data. append ([تاریخ ، باز ، بالا ، پایین ، نزدیک]) # قاب ارائه شده آخرین مرحله خود را پاک کنید.. render_data ، عرض = 0. 8/24 ، Colorup = 'Green' ، Colordown = 'Red' ، Alpha = 0. 8) # ما باید هر مرحله لایه ها را تنظیم کنیم ، زیرا ما در حال پاک کردن زیر مجموعه ها در هر مرحله Self. Ax2. Set_xlabel ("تاریخ" است) self. ax1. set_ylabel ('price') self. ax3. set_ylabel ('تعادل') "" نمایش تصویر با matplotlib - قطع سایر وظایف "" " # نمودار را بدون مسدود کردن بقیه برنامه plt. show نشان دهید (بلوک = نادرست) # لازم برای مشاهده فریم ها قبل از عدم وجود plt. pause (0. 001)

پس از اجرای کد فوق ، باید میله های زیبا OHCL را روی صفحه خود ببینیم:

بنابراین ، سخت ترین قسمت در حال حاضر انجام شده است. اکنون ما می خواهیم تاریخ و ارزش خالص و تاریخ و زیبایی را به طرح خود اضافه کنیم. همان کاری که با داده های OHCL خود انجام دادیم ، باید با افزودن آنها در لیست Deque ، داده های تاریخچه Volume و Net Worth را جمع آوری کنیم. به طور مشابه ، ما زیرمجموعه های AX2 و AX3 را پاک می کنیم ، تمام تاریخ ها را به یک لیست قرار می دهیم و زیرمجموعه AX2 را با حجم تاریخی خود پر می کنیم. مهمترین خطوط Self. ax1. xaxis. set_major_formatter (self. date_format) و self. fig. autofmt_xdate () است ، جایی که تمام قالب بندی تاریخ زیبا انجام می شود. برای افزودن ارزش خالص یکی از ساده ترین قسمت ها است ، ما خط زیر self. ax3. plot را اضافه می کنیم (date_render_range ، self. net_worth ، color = "blue"). در اینجا کد تا این نکته آورده شده است:

تجارت کلاس: def __init __ (خود ، render_range) :.# محیط را به صفحه نمایش ارائه دهید (خود ، تاریخ ، باز ، بالا ، پایین ، نزدیک ، حجم ، NET_WORTH ، معاملات): # ضمیمه حجم و net_worth to deque self. volume. append (جلد) self. net_worth. append(net_worth) # قبل از پیوستن به لیست deque ، نیاز به تبدیل تاریخ به تاریخ قالب ویژه = mpl_dates. date2num ([pd. to_datetime (تاریخ)]) [0] self. Render_Data. Append ([تاریخ ، باز ، بالا ، پایین ،CLOSE]) # فریم ارائه شده آخرین مرحله خود را پاک کنید. تمام تاریخ ها را به یک لیست قرار دهید و AX2 را با حجم date_render_range = [i [0] برای من در self. render_data] self. ax2. clear () خود. نمودار Net_Worth در AX3 (به اشتراک گذاشته شده با AX1) Subplot self. ax3. Clear () self. ax3. plot (date_render_range ، self. net_worth ، color = "blue") # زیبا سازی-labels (قالب تاریخ ما) self. ax1. xaxis. set_major_formatter (self. date_format) self. fig. autofmt_xdate () # ما باید هر مرحله لایه ها را تنظیم کنیم ، زیرا ما در حال پاک کردن زیرمجموعه های هر مرحله self. ax2. set_xlabel ("تاریخ") self. ax1. set_ylabel ('price') self. ax3. set_ylabel ('تعادل') # من از tright_layout برای جایگزینی plt. subplots_adjust خود استفاده می کنم. برنامه plt. show (block = false) # لازم برای مشاهده فریم ها قبل از عدم وجود plt. pause (0. 001)

همانطور که می بینید ، اکنون نمودار ما کاملاً آموزنده است ، روش های زیادی برای بهبود آن وجود دارد ، اما در این مرحله ، ما بیشتر دوست داریم بدانیم که سفارشات ما در کجا ساخته شده است ، بنابراین باید برخی از نقاط پیکان را اضافه کنیم.

برای پیدا کردن نحوه اضافه کردن فلش های قرمز و سبز زیبا به طرح ما مدتی طول کشید. اما سرانجام ، من نوع طرح متداول "طرح پراکندگی" ، یک پسر عموی نزدیک از طرح خط را پیدا کردم. به جای اینکه امتیازاتی که به بخش های خط پیوستند ، نقاط به صورت جداگانه با یک نقطه ، دایره یا شکل های دیگر نشان داده می شوند. این مکانی است که ما از برنامه اصلی خود از فرهنگ لغت خود استفاده خواهیم کرد. این مکان ممکن است کمی کندتر باشد زیرا من برای یافتن موقعیت تاریخ از حلقه استفاده می کنم ، جایی که سفارشات ما در تاریخ نقشه ساخته شده است. من یک فلش سبز یا قرمز را مطابق نوع سفارش قرار دادم ، اکنون کد بسیار ساده به نظر می رسد ، اما فکر می کنم این قسمت بیشترین زمان را برای من طول کشید.

تجارت کلاس: def __init __ (خود ، render_range) :.# محیط را به صفحه نمایش ارائه دهید (خود ، تاریخ ، باز ، بالا ، پایین ، نزدیک ، حجم ، NET_WORTH ، معاملات): # ضمیمه حجم و net_worth to deque self. volume. append (جلد) self. net_worth. append(net_worth) # قبل از پیوستن به لیست deque ، نیاز به تبدیل تاریخ به تاریخ قالب ویژه = mpl_dates. date2num ([pd. to_datetime (تاریخ)]) [0] self. Render_Data. Append ([تاریخ ، باز ، بالا ، پایین ،CLOSE]) # فریم ارائه شده آخرین مرحله خود را پاک کنید. تمام تاریخ ها را به یک لیست قرار دهید و AX2 را با حجم date_render_range = [i [0] برای من در self. render_data] self. ax2. clear () خود. نمودار Net_Worth در AX3 (به اشتراک گذاشته شده با AX1) Subplot self. ax3. Clear () self. ax3. plot (date_render_range ، self. net_worth ، color = "blue") # زیبا سازی-labels (قالب تاریخ ما) self. ax1. xaxis. set_major_formatter (self. date_format) self. fig. autofmt_xdate () # مرتب سازی و خرید سفارشات ، فلش ها را در موقعیت های سفارش مناسب برای تجارت در معاملات قرار دهید: trade_date = mpl_dates. date2num ([pd. to_datetime (trade [trade '']])]) [0] اگر Trade_date in Date_Render_range: اگر تجارت ['نوع'] == 'خرید': HIGH_LOW = تجارت ['LOW']-10 Self. ax1. scatter (Trade_date ، High_low ، C = 'Green' ،label = 'green' ، s = 120 ، edgecolors = 'none' ، marker = "^") other: high_low = trade ['high']+10 self. ax1. scatter (trade_date ، high_low ، c = 'red' ،label = 'red' ، s = 120 ، edgecolors = 'none' ، marker = "v") # ما باید در هر مرحله لایه ها را تنظیم کنیم ، زیرا ما در حال پاک کردن زیر مجموعه ها در هر مرحله self. ax2. set_xlabel ("تاریخ") هستیم. ax1. set_ylabel ('price') self. ax3. set_ylabel ('تعادل') # من برای جایگزینی plt. subplots_adjust خود استفاده می کنم. نمودار بدون مسدود کردن بقیه برنامه # plt. show (block = false) # لازم برای مشاهده فریم ها قبل از عدم وجود # plt. pause (0. 001) "" "تصویر نمایش با OpenCv - بدون قطع"canvas self. fig. canvas. draw () # تبدیل بوم به تصویر img = np. fromstring (self. fig. canvas. tostring_rgb () ، dtype = np. uint8 ، sep = ') img. reshape (خود. fig. canvas. get_width_height () [::-1] + (3 ،)) # IMG RGB است ، تبدیل به تصویر پیش فرض پیش فرض OpenCV = Cv2. cvtcolor (IMG ، CV2. Color_RGB2BGR) # تصویر نمایش با OpenCV یا هر عملیاتی شمامانند cv2. imshow ("ربات تجارت بیت کوین" ، تصویر) اگر cv2. waitkey (25) & 0xff == ord ("q"): cv2.

DestroyallWindows () بازگشت

همچنین ، ممکن است ببینید که من از عملکرد plt. show (block = false) تقدیر کردم. در عوض ، من توابع CV2 را برای نشان دادن تصویر خود نوشتم. من این کار را کردم زیرا در حالی که در هر مرحله از تجسم Matplotlib استفاده می کردم ، تمام وظایف ما قطع شد. ما نمی توانیم به نوشتن کد ، به حداقل رساندن آن یا هر نوع تایپ کردن با صفحه کلید خود ادامه دهیم. به عنوان یک راه حل ، دریافتم که بهترین راه حل استفاده از کتابخانه OpenCV است. و در اینجا آخرین تجسم زیبا از اقدامات ساخت بیت کوین ما انجام شده است.

نتیجه:

و همین است! اکنون ما یک تجسم زیبا و زنده از محیط تجاری تصادفی بیت کوین که در آموزش قبلی ایجاد کردیم ، داریم! ما هنوز زمان زیادی را برای آموزش به نماینده نحوه کسب درآمد کسب نکرده ایم ... ما این کار را در آموزش بعدی انجام خواهیم داد!

ما در اینجا کار فوق العاده ای انجام دادیم ، و اکنون وقتی نماینده آموزش دیده خود را انجام می دهیم ، می توانیم ارزیابی کنیم که آیا این اقدامات بهتر از تصادفی بوده یا آنها نبوده اند.

فارکس را از کجا شروع کنیم...
ما را در سایت فارکس را از کجا شروع کنیم دنبال می کنید

برچسب : نویسنده : لیما اصغرپورسازونی بازدید : 34 تاريخ : دوشنبه 5 تير 1402 ساعت: 16:20