Обновление зависимостей и игнорируемых файлов
- Добавлен yfinance в requirements.txt - Расширен .gitignore для исключения служебных файлов Python - Исправлен импорт в currency.py для корректной работы с модулями
This commit is contained in:
parent
74d4e14476
commit
61b6f03e26
6
.gitignore
vendored
6
.gitignore
vendored
@ -1 +1,7 @@
|
||||
venv/
|
||||
pycache/
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
__pycache__/
|
||||
__pycache__
|
||||
11
4.2.0
Normal file
11
4.2.0
Normal file
@ -0,0 +1,11 @@
|
||||
Requirement already satisfied: nbformat in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (5.10.4)
|
||||
Requirement already satisfied: fastjsonschema>=2.15 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from nbformat) (2.21.1)
|
||||
Requirement already satisfied: jsonschema>=2.6 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from nbformat) (4.23.0)
|
||||
Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from nbformat) (5.7.2)
|
||||
Requirement already satisfied: traitlets>=5.1 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from nbformat) (5.14.3)
|
||||
Requirement already satisfied: attrs>=22.2.0 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from jsonschema>=2.6->nbformat) (24.3.0)
|
||||
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from jsonschema>=2.6->nbformat) (2024.10.1)
|
||||
Requirement already satisfied: referencing>=0.28.4 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from jsonschema>=2.6->nbformat) (0.35.1)
|
||||
Requirement already satisfied: rpds-py>=0.7.1 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from jsonschema>=2.6->nbformat) (0.22.3)
|
||||
Requirement already satisfied: platformdirs>=2.5 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from jupyter-core!=5.0.*,>=4.12->nbformat) (4.3.6)
|
||||
Requirement already satisfied: pywin32>=300 in d:\pythonpython\globalsy\globalsy_streamlit\venv\lib\site-packages (from jupyter-core!=5.0.*,>=4.12->nbformat) (308)
|
||||
@ -134,3 +134,5 @@ class ForexDataHandler:
|
||||
raise ValueError(f"Неизвестный индекс: {index}")
|
||||
|
||||
return self.get_market_data(self.russian_indices[index])
|
||||
|
||||
|
||||
|
||||
70
classes/moex_class.py
Normal file
70
classes/moex_class.py
Normal file
@ -0,0 +1,70 @@
|
||||
import pandas as pd
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
class RussianMarketData:
|
||||
def __init__(self):
|
||||
self.moex_base_url = "https://iss.moex.com/iss"
|
||||
|
||||
# Словарь с индексами
|
||||
self.indices = {
|
||||
'oil_gas': 'MOEXOG', # Нефть и газ
|
||||
'finance': 'MOEXFN', # Финансы
|
||||
'telecom': 'MOEXTL', # Телекоммуникации
|
||||
'metals': 'MOEXMM', # Металлы и добыча
|
||||
'consumer': 'MOEXCN', # Потребительский сектор
|
||||
'transport': 'MOEXTN' # Транспорт
|
||||
}
|
||||
|
||||
def get_moex_index_history(self, index_code='MOEXOG', start_date=None, end_date=None):
|
||||
"""
|
||||
Получение исторических данных индекса MOEX.
|
||||
"""
|
||||
if start_date is None:
|
||||
start_date = (datetime.now() - timedelta(days=365)).strftime('%Y-%m-%d')
|
||||
if end_date is None:
|
||||
end_date = datetime.now().strftime('%Y-%m-%d')
|
||||
|
||||
all_data = []
|
||||
start = 0
|
||||
while True:
|
||||
url = f"{self.moex_base_url}/history/engines/stock/markets/index/securities/{index_code}.json"
|
||||
params = {
|
||||
'from': start_date,
|
||||
'till': end_date,
|
||||
'start': start
|
||||
}
|
||||
|
||||
response = requests.get(url, params=params)
|
||||
data = response.json()
|
||||
|
||||
# Проверка наличия данных
|
||||
if 'history' not in data or len(data['history']['data']) == 0:
|
||||
break
|
||||
|
||||
# Добавление данных в общий список
|
||||
all_data.extend(data['history']['data'])
|
||||
start += 100 # Увеличиваем смещение на 100 для следующего запроса
|
||||
|
||||
# Преобразование данных в DataFrame
|
||||
columns = data['history']['columns']
|
||||
df = pd.DataFrame(all_data, columns=columns)
|
||||
|
||||
# Обработка данных
|
||||
df['TRADEDATE'] = pd.to_datetime(df['TRADEDATE'])
|
||||
df = df.set_index('TRADEDATE')
|
||||
|
||||
return df[['CLOSE', 'VOLUME']]
|
||||
|
||||
def get_historical_data(self, sector: str, start_date=None, end_date=None):
|
||||
"""
|
||||
Получает исторические данные для указанного сектора.
|
||||
|
||||
Args:
|
||||
sector: ключ сектора из словаря indices
|
||||
"""
|
||||
if sector not in self.indices:
|
||||
raise ValueError(f"Неизвестный сектор: {sector}")
|
||||
|
||||
index_code = self.indices[sector]
|
||||
return self.get_moex_index_history(index_code, start_date, end_date)
|
||||
228
classes/moex_history.py
Normal file
228
classes/moex_history.py
Normal file
@ -0,0 +1,228 @@
|
||||
import pandas as pd
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Dict, Optional
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import numpy as np
|
||||
|
||||
class MOEXHistoricalData:
|
||||
def __init__(self):
|
||||
self.base_url = "https://iss.moex.com/iss"
|
||||
|
||||
# Словарь соответствия секторов и их индексов на MOEX
|
||||
self.sector_indices = {
|
||||
'metals_mining': 'MOEXMM', # Индекс Металлов и добычи
|
||||
'oil_gas': 'MOEXOG', # Индекс Нефти и газа
|
||||
'chemicals': 'MOEXCH', # Индекс Химии и нефтехимии
|
||||
'electric_utilities': 'MOEXEU', # Индекс Электроэнергетики
|
||||
'telecom': 'MOEXTL', # Индекс Телекоммуникаций
|
||||
'finance': 'MOEXFN', # Индекс Финансов
|
||||
'consumer': 'MOEXCN', # Индекс Потребительского сектора
|
||||
'transport': 'MOEXTN' # Индекс Транспорта
|
||||
}
|
||||
|
||||
async def get_security_history(
|
||||
self,
|
||||
ticker: str,
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
engine: str = "stock",
|
||||
market: str = "shares",
|
||||
board: str = "TQBR"
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
Получение исторических данных по отдельному тикеру
|
||||
|
||||
Args:
|
||||
ticker: Тикер акции
|
||||
start_date: Начальная дата в формате YYYY-MM-DD
|
||||
end_date: Конечная дата в формате YYYY-MM-DD
|
||||
engine: Торговый движок (по умолчанию stock)
|
||||
market: Рынок (по умолчанию shares)
|
||||
board: Режим торгов (по умолчанию TQBR)
|
||||
|
||||
Returns:
|
||||
DataFrame с историческими данными
|
||||
"""
|
||||
url = f"{self.base_url}/history/engines/{engine}/markets/{market}/boards/{board}/securities/{ticker}.json"
|
||||
|
||||
all_data = []
|
||||
start = 0
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
while True:
|
||||
params = {
|
||||
"from": start_date,
|
||||
"till": end_date,
|
||||
"start": start,
|
||||
"limit": 100
|
||||
}
|
||||
|
||||
async with session.get(url, params=params) as response:
|
||||
data = await response.json()
|
||||
|
||||
# Получаем данные истории
|
||||
history_data = data['history']
|
||||
|
||||
if not history_data['data']:
|
||||
break
|
||||
|
||||
# Добавляем данные в общий список
|
||||
all_data.extend(history_data['data'])
|
||||
start += 100
|
||||
|
||||
if len(history_data['data']) < 100:
|
||||
break
|
||||
|
||||
# Создаем DataFrame
|
||||
df = pd.DataFrame(all_data, columns=history_data['columns'])
|
||||
|
||||
# Конвертируем даты и числовые значения
|
||||
df['TRADEDATE'] = pd.to_datetime(df['TRADEDATE'])
|
||||
numeric_columns = ['OPEN', 'HIGH', 'LOW', 'CLOSE', 'VALUE', 'VOLUME']
|
||||
df[numeric_columns] = df[numeric_columns].apply(pd.to_numeric)
|
||||
|
||||
return df
|
||||
|
||||
async def get_sector_history(
|
||||
self,
|
||||
sector_tickers: List[str],
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
engine: str = "stock",
|
||||
market: str = "shares",
|
||||
board: str = "TQBR"
|
||||
) -> Dict[str, pd.DataFrame]:
|
||||
"""
|
||||
Получение исторических данных по всем тикерам сектора
|
||||
|
||||
Args:
|
||||
sector_tickers: Список тикеров сектора
|
||||
start_date: Начальная дата в формате YYYY-MM-DD
|
||||
end_date: Конечная дата в формате YYYY-MM-DD
|
||||
engine: Торговый движок (по умолчанию stock)
|
||||
market: Рынок (по умолчанию shares)
|
||||
board: Режим торгов (по умолчанию TQBR)
|
||||
|
||||
Returns:
|
||||
Словарь {тикер: DataFrame с историческими данными}
|
||||
"""
|
||||
tasks = []
|
||||
for ticker in sector_tickers:
|
||||
task = self.get_security_history(
|
||||
ticker=ticker,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
engine=engine,
|
||||
market=market,
|
||||
board=board
|
||||
)
|
||||
tasks.append(task)
|
||||
|
||||
results = await asyncio.gather(*tasks)
|
||||
return dict(zip(sector_tickers, results))
|
||||
|
||||
async def get_official_sector_index(
|
||||
self,
|
||||
sector: str,
|
||||
start_date: str,
|
||||
end_date: str
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
Получение официального отраслевого индекса с MOEX
|
||||
|
||||
Args:
|
||||
sector: Название сектора (ключ из словаря sector_indices)
|
||||
start_date: Начальная дата в формате YYYY-MM-DD
|
||||
end_date: Конечная дата в формате YYYY-MM-DD
|
||||
|
||||
Returns:
|
||||
DataFrame с данными индекса
|
||||
"""
|
||||
if sector not in self.sector_indices:
|
||||
raise ValueError(f"Неизвестный сектор: {sector}. Доступные секторы: {list(self.sector_indices.keys())}")
|
||||
|
||||
index_ticker = self.sector_indices[sector]
|
||||
url = f"{self.base_url}/history/engines/stock/markets/index/securities/{index_ticker}.json"
|
||||
|
||||
all_data = []
|
||||
start = 0
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
while True:
|
||||
params = {
|
||||
"from": start_date,
|
||||
"till": end_date,
|
||||
"start": start,
|
||||
"limit": 100
|
||||
}
|
||||
|
||||
async with session.get(url, params=params) as response:
|
||||
data = await response.json()
|
||||
|
||||
history_data = data['history']
|
||||
|
||||
if not history_data['data']:
|
||||
break
|
||||
|
||||
all_data.extend(history_data['data'])
|
||||
start += 100
|
||||
|
||||
if len(history_data['data']) < 100:
|
||||
break
|
||||
|
||||
df = pd.DataFrame(all_data, columns=history_data['columns'])
|
||||
|
||||
# Конвертируем даты и числовые значения
|
||||
df['TRADEDATE'] = pd.to_datetime(df['TRADEDATE'])
|
||||
numeric_columns = ['OPEN', 'HIGH', 'LOW', 'CLOSE', 'VALUE', 'VOLUME']
|
||||
df[numeric_columns] = df[numeric_columns].apply(pd.to_numeric)
|
||||
|
||||
return df
|
||||
|
||||
def calculate_sector_index(
|
||||
self,
|
||||
sector_data: Dict[str, pd.DataFrame],
|
||||
weights: Optional[Dict[str, float]] = None
|
||||
) -> pd.DataFrame:
|
||||
"""
|
||||
Расчет индекса сектора на основе исторических данных входящих в него компаний
|
||||
|
||||
Args:
|
||||
sector_data: Словарь с историческими данными по тикерам {тикер: DataFrame}
|
||||
weights: Словарь с весами компаний {тикер: вес}. Если None, веса будут равными
|
||||
|
||||
Returns:
|
||||
DataFrame с рассчитанным индексом сектора
|
||||
"""
|
||||
# Если веса не указаны, используем равные веса
|
||||
if weights is None:
|
||||
weights = {ticker: 1/len(sector_data) for ticker in sector_data.keys()}
|
||||
|
||||
# Создаем DataFrame с датами и ценами закрытия для каждого тикера
|
||||
prices_df = pd.DataFrame()
|
||||
|
||||
for ticker, df in sector_data.items():
|
||||
prices_df[ticker] = df.set_index('TRADEDATE')['CLOSE']
|
||||
|
||||
# Рассчитываем относительное изменение цен
|
||||
returns_df = prices_df.pct_change()
|
||||
|
||||
# Рассчитываем взвешенную доходность индекса
|
||||
weighted_returns = pd.DataFrame()
|
||||
for ticker in returns_df.columns:
|
||||
weighted_returns[ticker] = returns_df[ticker] * weights[ticker]
|
||||
|
||||
index_returns = weighted_returns.sum(axis=1)
|
||||
|
||||
# Рассчитываем значения индекса
|
||||
index_values = (1 + index_returns).cumprod() * 1000 # Начальное значение 1000
|
||||
|
||||
# Создаем итоговый DataFrame
|
||||
result_df = pd.DataFrame({
|
||||
'INDEX_VALUE': index_values,
|
||||
'INDEX_RETURN': index_returns
|
||||
})
|
||||
|
||||
return result_df
|
||||
255
config.py
Normal file
255
config.py
Normal file
@ -0,0 +1,255 @@
|
||||
sector_indices = {
|
||||
'metals_mining': 'MOEXMM', # Индекс Металлов и добычи
|
||||
'oil_gas': 'MOEXOG', # Индекс Нефти и газа
|
||||
'chemicals': 'MOEXCH', # Индекс Химии и нефтехимии
|
||||
'electric_utilities': 'MOEXEU', # Индекс Электроэнергетики
|
||||
'telecom': 'MOEXTL', # Индекс Телекоммуникаций
|
||||
'finance': 'MOEXFN', # Индекс Финансов
|
||||
'consumer': 'MOEXCN', # Индекс Потребительского сектора
|
||||
'transport': 'MOEXTN' # Индекс Транспорта
|
||||
}
|
||||
|
||||
sector_tickers = {'metals_mining': ['ALRS',
|
||||
'AMEZ',
|
||||
'BELO',
|
||||
'BLNG',
|
||||
'CHEP',
|
||||
'CHMF',
|
||||
'CHMK',
|
||||
'CHZN',
|
||||
'ENPG',
|
||||
'GMKN',
|
||||
'KBTK',
|
||||
'KOGK',
|
||||
'LNZL',
|
||||
'LNZLP',
|
||||
'MAGN',
|
||||
'MGOK',
|
||||
'MTLR',
|
||||
'MTLRP',
|
||||
'NLMK',
|
||||
'PGIL',
|
||||
'PLZL',
|
||||
'PMTL',
|
||||
'POGR',
|
||||
'POLY',
|
||||
'RASP',
|
||||
'RUAL',
|
||||
'RUALR',
|
||||
'SELG',
|
||||
'SELGP',
|
||||
'TRMK',
|
||||
'UGLD',
|
||||
'UNKL',
|
||||
'VSMO',
|
||||
'VSMZ'],
|
||||
'oil_gas': ['BANE',
|
||||
'BANEP',
|
||||
'GAZP',
|
||||
'JNOSP',
|
||||
'KRKNP',
|
||||
'LKOH',
|
||||
'MFGS',
|
||||
'MFGSP',
|
||||
'NOTK',
|
||||
'NVTK',
|
||||
'RITK',
|
||||
'RNFT',
|
||||
'RNHSP',
|
||||
'ROSN',
|
||||
'SIBN',
|
||||
'SNGS',
|
||||
'SNGSP',
|
||||
'TATN',
|
||||
'TATNP',
|
||||
'TNBP',
|
||||
'TNBPP',
|
||||
'TRMK',
|
||||
'TRNFP'],
|
||||
'chemicals': ['AKRN',
|
||||
'AZKM',
|
||||
'DGBZ',
|
||||
'DGBZP',
|
||||
'KAZT',
|
||||
'KZOS',
|
||||
'KZOSP',
|
||||
'MGNZ',
|
||||
'NKNC',
|
||||
'NKNCP',
|
||||
'OMSH',
|
||||
'PHOR',
|
||||
'SILV',
|
||||
'URKA',
|
||||
'YASH'],
|
||||
'electric_utilities': ['ARSB',
|
||||
'BEGY',
|
||||
'DVEC',
|
||||
'EESR',
|
||||
'EESRP',
|
||||
'ELFV',
|
||||
'ENRU',
|
||||
'EONR',
|
||||
'FEES',
|
||||
'HYDR',
|
||||
'IRAO',
|
||||
'IRGZ',
|
||||
'KISB',
|
||||
'KRNG',
|
||||
'KRSG',
|
||||
'LSNG',
|
||||
'LSNGP',
|
||||
'MGSV',
|
||||
'MRKC',
|
||||
'MRKH',
|
||||
'MRKK',
|
||||
'MRKP',
|
||||
'MRKS',
|
||||
'MRKU',
|
||||
'MRKV',
|
||||
'MRKY',
|
||||
'MRKZ',
|
||||
'MSNG',
|
||||
'MSRS',
|
||||
'MSSB',
|
||||
'MSSV',
|
||||
'OGK1',
|
||||
'OGK2',
|
||||
'OGK4',
|
||||
'OGK6',
|
||||
'OGKA',
|
||||
'OGKB',
|
||||
'OGKC',
|
||||
'OGKD',
|
||||
'OGKE',
|
||||
'OGKF',
|
||||
'RSTI',
|
||||
'RSTIP',
|
||||
'SAGO',
|
||||
'SARE',
|
||||
'SVER',
|
||||
'TGKA',
|
||||
'TGKB',
|
||||
'TGKD',
|
||||
'TGKE',
|
||||
'TGKF',
|
||||
'TGKH',
|
||||
'TGKI',
|
||||
'TGKJ',
|
||||
'TGKN',
|
||||
'TNSE',
|
||||
'UPRO',
|
||||
'VRAO',
|
||||
'VTGK',
|
||||
'YKEN'],
|
||||
'telecom': ['AFKC',
|
||||
'AFKS',
|
||||
'BISV',
|
||||
'BISVP',
|
||||
'CMST',
|
||||
'CNTL',
|
||||
'CNTLP',
|
||||
'CTLK',
|
||||
'DLSV',
|
||||
'DLSVP',
|
||||
'MFON',
|
||||
'MGTS',
|
||||
'MGTSP',
|
||||
'MTSI',
|
||||
'MTSS',
|
||||
'RTKM',
|
||||
'RTKMP',
|
||||
'SPTL',
|
||||
'SPTLP',
|
||||
'STKM',
|
||||
'STKMP',
|
||||
'TTLK',
|
||||
'URSI',
|
||||
'URSIP',
|
||||
'UTEL',
|
||||
'VTEL',
|
||||
'VTELP'],
|
||||
'finance': ['AFKS',
|
||||
'BSPB',
|
||||
'BSPBP',
|
||||
'CBOM',
|
||||
'EPLN',
|
||||
'FTRE',
|
||||
'LEAS',
|
||||
'MBNK',
|
||||
'MMBM',
|
||||
'MOEX',
|
||||
'PSBR',
|
||||
'QIWI',
|
||||
'RENI',
|
||||
'ROSB',
|
||||
'SBER',
|
||||
'SBERP',
|
||||
'SFIN',
|
||||
'SPBE',
|
||||
'T',
|
||||
'TAVR',
|
||||
'TCSG',
|
||||
'TRHN',
|
||||
'URSAP',
|
||||
'VTBR',
|
||||
'VTBS',
|
||||
'VZRZ',
|
||||
'VZRZP',
|
||||
'YRSL',
|
||||
'ZAYM'],
|
||||
'consumer': ['ABIO',
|
||||
'AGRO',
|
||||
'APTK',
|
||||
'AQUA',
|
||||
'AVAZ',
|
||||
'AVAZP',
|
||||
'BELU',
|
||||
'DELI',
|
||||
'DIXY',
|
||||
'DSKY',
|
||||
'EUTR',
|
||||
'FIVE',
|
||||
'FIXP',
|
||||
'GCHE',
|
||||
'GEMC',
|
||||
'GRAZ',
|
||||
'HNFG',
|
||||
'ISKJ',
|
||||
'KLNA',
|
||||
'LENT',
|
||||
'LIFE',
|
||||
'LNTA',
|
||||
'MDMG',
|
||||
'MGNT',
|
||||
'MVID',
|
||||
'OBUV',
|
||||
'OKEY',
|
||||
'ORUP',
|
||||
'OTCP',
|
||||
'PHST',
|
||||
'PKBA',
|
||||
'PKBAP',
|
||||
'PRMD',
|
||||
'PRTK',
|
||||
'ROST',
|
||||
'RSEA',
|
||||
'SCOH',
|
||||
'SCON',
|
||||
'SVAV',
|
||||
'SYNG',
|
||||
'VFRM',
|
||||
'VRPH',
|
||||
'VSEH',
|
||||
'WBDF',
|
||||
'WUSH',
|
||||
'YNDX'],
|
||||
'transport': ['AFLT',
|
||||
'FESH',
|
||||
'FLOT',
|
||||
'GLTR',
|
||||
'GTRK',
|
||||
'NKHP',
|
||||
'NMTP',
|
||||
'TAER',
|
||||
'TRCN',
|
||||
'UTAR']}
|
||||
@ -1,5 +1,11 @@
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Добавляем путь к родительской директории
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
|
||||
import sqlite3
|
||||
from exchange import ForexDataHandler
|
||||
from classes.exchange import ForexDataHandler
|
||||
|
||||
# Создаем или подключаемся к базе данных
|
||||
conn = sqlite3.connect('currency_rates.db')
|
||||
|
||||
101
get/tick_history.py
Normal file
101
get/tick_history.py
Normal file
@ -0,0 +1,101 @@
|
||||
import pandas as pd
|
||||
import os
|
||||
import sys
|
||||
import sqlite3
|
||||
from datetime import datetime, timedelta
|
||||
import asyncio
|
||||
# Добавляем путь к родительской директории
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||||
from classes.moex_history import MOEXHistoricalData
|
||||
from config import sector_tickers
|
||||
|
||||
|
||||
class DataLoader:
|
||||
def __init__(self, db_path: str):
|
||||
"""
|
||||
Инициализация загрузчика данных.
|
||||
|
||||
Args:
|
||||
db_path: Путь к файлу базы данных SQLite
|
||||
"""
|
||||
self.db_path = db_path
|
||||
self.moex_data_handler = MOEXHistoricalData()
|
||||
|
||||
def _get_connection(self):
|
||||
"""
|
||||
Создает и возвращает соединение с базой данных.
|
||||
|
||||
Returns:
|
||||
sqlite3.Connection: Объект соединения с базой данных
|
||||
"""
|
||||
return sqlite3.connect(self.db_path)
|
||||
|
||||
async def load_sector_data(self, sector: str):
|
||||
"""
|
||||
Получение и сохранение исторических данных по сектору.
|
||||
|
||||
Args:
|
||||
sector: Название сектора
|
||||
"""
|
||||
end_date = datetime.now()
|
||||
start_date = end_date - timedelta(days=730) # За последние 2 года
|
||||
|
||||
# Получаем данные по официальному секторному индексу
|
||||
sector_df = await self.moex_data_handler.get_official_sector_index(
|
||||
sector,
|
||||
start_date.strftime('%Y-%m-%d'),
|
||||
end_date.strftime('%Y-%m-%d')
|
||||
)
|
||||
|
||||
# Сохраняем данные в таблицу
|
||||
with self._get_connection() as conn:
|
||||
sector_df.to_sql(sector, conn, if_exists='replace', index=False)
|
||||
print(f"Данные для сектора '{sector}' сохранены в таблице '{sector}'.")
|
||||
|
||||
async def load_ticker_data(self, tickers: list):
|
||||
"""
|
||||
Получение и сохранение исторических данных по тикерам.
|
||||
|
||||
Args:
|
||||
tickers: Список тикеров
|
||||
"""
|
||||
end_date = datetime.now()
|
||||
start_date = end_date - timedelta(days=730) # За последние 2 года
|
||||
|
||||
tasks = []
|
||||
for ticker in tickers:
|
||||
task = self.moex_data_handler.get_security_history(
|
||||
ticker,
|
||||
start_date.strftime('%Y-%m-%d'),
|
||||
end_date.strftime('%Y-%m-%d')
|
||||
)
|
||||
tasks.append(task)
|
||||
|
||||
results = await asyncio.gather(*tasks)
|
||||
|
||||
with self._get_connection() as conn:
|
||||
for ticker, df in zip(tickers, results):
|
||||
df.to_sql(ticker, conn, if_exists='replace', index=False)
|
||||
print(f"Данные для тикера '{ticker}' сохранены в таблице '{ticker}'.")
|
||||
|
||||
async def load_data(self, sector: str, tickers: list):
|
||||
"""
|
||||
Загрузка данных по сектору и тикерам.
|
||||
|
||||
Args:
|
||||
sector: Название сектора
|
||||
tickers: Список тикеров
|
||||
"""
|
||||
await asyncio.gather(
|
||||
self.load_sector_data(sector),
|
||||
self.load_ticker_data(tickers)
|
||||
)
|
||||
|
||||
# Пример использования
|
||||
if __name__ == "__main__":
|
||||
db_path = 'moex_data.db' # Путь к файлу базы данных SQLite
|
||||
data_loader = DataLoader(db_path)
|
||||
|
||||
|
||||
for sector in sector_tickers.keys():
|
||||
asyncio.run(data_loader.load_data(sector, sector_tickers[sector]))
|
||||
29
get_news_and_analyze.py
Normal file
29
get_news_and_analyze.py
Normal file
@ -0,0 +1,29 @@
|
||||
from openai import OpenAI
|
||||
|
||||
client = OpenAI(
|
||||
base_url="https://openrouter.ai/api/v1",
|
||||
api_key="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",
|
||||
)
|
||||
|
||||
completion = client.chat.completions.create(
|
||||
extra_body={},
|
||||
model="google/gemini-2.0-pro-exp-02-05:free",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "What is in this image?"
|
||||
},
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
)
|
||||
print(completion.choices[0].message.content)
|
||||
1668
open_router.ipynb
Normal file
1668
open_router.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -15,4 +15,5 @@ seaborn
|
||||
statsmodels
|
||||
xgboost
|
||||
lightgbm
|
||||
groq
|
||||
groq
|
||||
yfinance
|
||||
262
sector_tickers.json
Normal file
262
sector_tickers.json
Normal file
@ -0,0 +1,262 @@
|
||||
{
|
||||
"metals_mining": [
|
||||
"ALRS",
|
||||
"AMEZ",
|
||||
"BELO",
|
||||
"BLNG",
|
||||
"CHEP",
|
||||
"CHMF",
|
||||
"CHMK",
|
||||
"CHZN",
|
||||
"ENPG",
|
||||
"GMKN",
|
||||
"KBTK",
|
||||
"KOGK",
|
||||
"LNZL",
|
||||
"LNZLP",
|
||||
"MAGN",
|
||||
"MGOK",
|
||||
"MTLR",
|
||||
"MTLRP",
|
||||
"NLMK",
|
||||
"PGIL",
|
||||
"PLZL",
|
||||
"PMTL",
|
||||
"POGR",
|
||||
"POLY",
|
||||
"RASP",
|
||||
"RUAL",
|
||||
"RUALR",
|
||||
"SELG",
|
||||
"SELGP",
|
||||
"TRMK",
|
||||
"UGLD",
|
||||
"UNKL",
|
||||
"VSMO",
|
||||
"VSMZ"
|
||||
],
|
||||
"oil_gas": [
|
||||
"BANE",
|
||||
"BANEP",
|
||||
"GAZP",
|
||||
"JNOSP",
|
||||
"KRKNP",
|
||||
"LKOH",
|
||||
"MFGS",
|
||||
"MFGSP",
|
||||
"NOTK",
|
||||
"NVTK",
|
||||
"RITK",
|
||||
"RNFT",
|
||||
"RNHSP",
|
||||
"ROSN",
|
||||
"SIBN",
|
||||
"SNGS",
|
||||
"SNGSP",
|
||||
"TATN",
|
||||
"TATNP",
|
||||
"TNBP",
|
||||
"TNBPP",
|
||||
"TRMK",
|
||||
"TRNFP"
|
||||
],
|
||||
"chemicals": [
|
||||
"AKRN",
|
||||
"AZKM",
|
||||
"DGBZ",
|
||||
"DGBZP",
|
||||
"KAZT",
|
||||
"KZOS",
|
||||
"KZOSP",
|
||||
"MGNZ",
|
||||
"NKNC",
|
||||
"NKNCP",
|
||||
"OMSH",
|
||||
"PHOR",
|
||||
"SILV",
|
||||
"URKA",
|
||||
"YASH"
|
||||
],
|
||||
"electric_utilities": [
|
||||
"ARSB",
|
||||
"BEGY",
|
||||
"DVEC",
|
||||
"EESR",
|
||||
"EESRP",
|
||||
"ELFV",
|
||||
"ENRU",
|
||||
"EONR",
|
||||
"FEES",
|
||||
"HYDR",
|
||||
"IRAO",
|
||||
"IRGZ",
|
||||
"KISB",
|
||||
"KRNG",
|
||||
"KRSG",
|
||||
"LSNG",
|
||||
"LSNGP",
|
||||
"MGSV",
|
||||
"MRKC",
|
||||
"MRKH",
|
||||
"MRKK",
|
||||
"MRKP",
|
||||
"MRKS",
|
||||
"MRKU",
|
||||
"MRKV",
|
||||
"MRKY",
|
||||
"MRKZ",
|
||||
"MSNG",
|
||||
"MSRS",
|
||||
"MSSB",
|
||||
"MSSV",
|
||||
"OGK1",
|
||||
"OGK2",
|
||||
"OGK4",
|
||||
"OGK6",
|
||||
"OGKA",
|
||||
"OGKB",
|
||||
"OGKC",
|
||||
"OGKD",
|
||||
"OGKE",
|
||||
"OGKF",
|
||||
"RSTI",
|
||||
"RSTIP",
|
||||
"SAGO",
|
||||
"SARE",
|
||||
"SVER",
|
||||
"TGKA",
|
||||
"TGKB",
|
||||
"TGKD",
|
||||
"TGKE",
|
||||
"TGKF",
|
||||
"TGKH",
|
||||
"TGKI",
|
||||
"TGKJ",
|
||||
"TGKN",
|
||||
"TNSE",
|
||||
"UPRO",
|
||||
"VRAO",
|
||||
"VTGK",
|
||||
"YKEN"
|
||||
],
|
||||
"telecom": [
|
||||
"AFKC",
|
||||
"AFKS",
|
||||
"BISV",
|
||||
"BISVP",
|
||||
"CMST",
|
||||
"CNTL",
|
||||
"CNTLP",
|
||||
"CTLK",
|
||||
"DLSV",
|
||||
"DLSVP",
|
||||
"MFON",
|
||||
"MGTS",
|
||||
"MGTSP",
|
||||
"MTSI",
|
||||
"MTSS",
|
||||
"RTKM",
|
||||
"RTKMP",
|
||||
"SPTL",
|
||||
"SPTLP",
|
||||
"STKM",
|
||||
"STKMP",
|
||||
"TTLK",
|
||||
"URSI",
|
||||
"URSIP",
|
||||
"UTEL",
|
||||
"VTEL",
|
||||
"VTELP"
|
||||
],
|
||||
"finance": [
|
||||
"AFKS",
|
||||
"BSPB",
|
||||
"BSPBP",
|
||||
"CBOM",
|
||||
"EPLN",
|
||||
"FTRE",
|
||||
"LEAS",
|
||||
"MBNK",
|
||||
"MMBM",
|
||||
"MOEX",
|
||||
"PSBR",
|
||||
"QIWI",
|
||||
"RENI",
|
||||
"ROSB",
|
||||
"SBER",
|
||||
"SBERP",
|
||||
"SFIN",
|
||||
"SPBE",
|
||||
"T",
|
||||
"TAVR",
|
||||
"TCSG",
|
||||
"TRHN",
|
||||
"URSAP",
|
||||
"VTBR",
|
||||
"VTBS",
|
||||
"VZRZ",
|
||||
"VZRZP",
|
||||
"YRSL",
|
||||
"ZAYM"
|
||||
],
|
||||
"consumer": [
|
||||
"ABIO",
|
||||
"AGRO",
|
||||
"APTK",
|
||||
"AQUA",
|
||||
"AVAZ",
|
||||
"AVAZP",
|
||||
"BELU",
|
||||
"DELI",
|
||||
"DIXY",
|
||||
"DSKY",
|
||||
"EUTR",
|
||||
"FIVE",
|
||||
"FIXP",
|
||||
"GCHE",
|
||||
"GEMC",
|
||||
"GRAZ",
|
||||
"HNFG",
|
||||
"ISKJ",
|
||||
"KLNA",
|
||||
"LENT",
|
||||
"LIFE",
|
||||
"LNTA",
|
||||
"MDMG",
|
||||
"MGNT",
|
||||
"MVID",
|
||||
"OBUV",
|
||||
"OKEY",
|
||||
"ORUP",
|
||||
"OTCP",
|
||||
"PHST",
|
||||
"PKBA",
|
||||
"PKBAP",
|
||||
"PRMD",
|
||||
"PRTK",
|
||||
"ROST",
|
||||
"RSEA",
|
||||
"SCOH",
|
||||
"SCON",
|
||||
"SVAV",
|
||||
"SYNG",
|
||||
"VFRM",
|
||||
"VRPH",
|
||||
"VSEH",
|
||||
"WBDF",
|
||||
"WUSH",
|
||||
"YNDX"
|
||||
],
|
||||
"transport": [
|
||||
"AFLT",
|
||||
"FESH",
|
||||
"FLOT",
|
||||
"GLTR",
|
||||
"GTRK",
|
||||
"NKHP",
|
||||
"NMTP",
|
||||
"TAER",
|
||||
"TRCN",
|
||||
"UTAR"
|
||||
]
|
||||
}
|
||||
2269
test.ipynb
Normal file
2269
test.ipynb
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user