File vizualization.py of Package fint-bot
import matplotlib.pyplot as plt
from datetime import datetime
import warnings
class Visualizer:
def __init__(self, ticker, currency):
self.ticker = ticker
self.currency = currency
self.buys = []
self.sells = []
self.prices = {}
self._setup_plot()
def _setup_plot(self):
"""Настройка графика с обработкой ошибок"""
try:
# Пробуем интерактивный режим
plt.ion()
self.fig = plt.figure(figsize=(12, 6))
self.ax = self.fig.add_subplot(111)
self.gui_available = True
print(f"Визуализатор инициализирован для {self.ticker}")
except Exception as e:
# Если GUI недоступен, отключаем визуализацию
self.fig = None
self.ax = None
self.gui_available = False
print(f"Визуализация отключена: {e}")
warnings.warn(f"GUI недоступен. Визуализация отключена для {self.ticker}")
def add_price(self, time, price: float):
"""Добавление новой цены"""
# Сохраняем цену
if hasattr(time, 'isoformat'):
time_key = time
else:
time_key = time
self.prices[time_key] = price
# Обновляем график если GUI доступен
if self.gui_available:
self.update_plot()
def add_buy(self, time):
"""Добавление точки покупки"""
if hasattr(time, 'isoformat'):
time_key = time
else:
time_key = time
self.buys.append(time_key)
if self.gui_available:
# Обновляем график, чтобы показать покупку
self.update_plot()
def add_sell(self, time):
"""Добавление точки продажи"""
if hasattr(time, 'isoformat'):
time_key = time
else:
time_key = time
self.sells.append(time_key)
if self.gui_available:
# Обновляем график, чтобы показать продажу
self.update_plot()
def update_plot(self):
"""Обновление графика"""
if not self.gui_available or not self.fig or not self.ax:
return
if not self.prices: # Нет данных для отображения
return
try:
self.ax.clear()
# Сортируем цены по времени
sorted_times = sorted(self.prices.keys())
sorted_prices = [self.prices[t] for t in sorted_times]
# Берем последние 50 точек или все, если меньше
if len(sorted_times) > 50:
x = sorted_times[-50:]
y = sorted_prices[-50:]
else:
x = sorted_times
y = sorted_prices
if not x: # Проверка на случай пустого списка
return
# Рисуем график цены
self.ax.plot(x, y, 'b-', linewidth=1.5, label='Price')
self.ax.set_title(f'{self.ticker} - Price Chart')
self.ax.set_xlabel('Time')
self.ax.set_ylabel(f'Price ({self.currency})')
self.ax.grid(True, alpha=0.3)
self.ax.legend()
# Отображаем точки покупок и продаж на видимом интервале
if y:
min_y = min(y)
max_y = max(y)
visible_min_time = x[0]
# Покупки (зеленые линии)
buys_in_range = [buy for buy in self.buys if buy >= visible_min_time]
if buys_in_range:
self.ax.vlines(buys_in_range, ymin=min_y, ymax=max_y,
color='g', linewidth=1.2, alpha=0.6,
label='Buy', linestyle='--')
# Продажи (красные линии)
sells_in_range = [sell for sell in self.sells if sell >= visible_min_time]
if sells_in_range:
self.ax.vlines(sells_in_range, ymin=min_y, ymax=max_y,
color='r', linewidth=1.2, alpha=0.6,
label='Sell', linestyle='--')
# Автоматическая настройка меток времени
if x:
self.ax.tick_params(axis='x', rotation=45)
plt.tight_layout()
# Обновляем график
self.fig.canvas.draw()
self.fig.canvas.flush_events()
plt.pause(0.01) # Короткая пауза для обновления
except Exception as e:
print(f"Ошибка при обновлении графика: {e}")
self.gui_available = False
def save_plot(self, filename=None):
"""Сохранение графика в файл"""
if not self.gui_available:
print("Невозможно сохранить график: GUI недоступен")
return
if filename is None:
filename = f"{self.ticker}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
try:
self.fig.savefig(filename, dpi=150, bbox_inches='tight')
print(f"График сохранен в {filename}")
except Exception as e:
print(f"Ошибка при сохранении графика: {e}")
def close(self):
"""Закрытие графика"""
if self.gui_available and self.fig:
try:
plt.close(self.fig)
except:
pass
def __del__(self):
"""Деструктор для закрытия графика"""
self.close()