|
|
import httpx
|
|
|
import random
|
|
|
from datetime import datetime, timedelta
|
|
|
from typing import List, Optional
|
|
|
from loguru import logger
|
|
|
from tenacity import retry, stop_after_attempt, wait_exponential
|
|
|
|
|
|
from adapters.base import BaseDataAdapter
|
|
|
from models import (
|
|
|
MarketOverview,
|
|
|
MarketIndex,
|
|
|
SentimentData,
|
|
|
MomentumData,
|
|
|
HighLowStock,
|
|
|
PriceDistribution,
|
|
|
AIAnalysis,
|
|
|
KLineData,
|
|
|
NewsItem,
|
|
|
HotNews,
|
|
|
SentimentTrend,
|
|
|
Stock,
|
|
|
RecommendationType,
|
|
|
TrendType,
|
|
|
SentimentType,
|
|
|
TargetPrice,
|
|
|
)
|
|
|
from config import settings
|
|
|
|
|
|
|
|
|
class EastmoneyAdapter(BaseDataAdapter):
|
|
|
def __init__(self):
|
|
|
super().__init__("东方财富", settings.EASTMONEY_API)
|
|
|
self._client: Optional[httpx.AsyncClient] = None
|
|
|
|
|
|
async def _get_client(self) -> httpx.AsyncClient:
|
|
|
if self._client is None:
|
|
|
self._client = httpx.AsyncClient(
|
|
|
timeout=10.0,
|
|
|
headers={
|
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
|
"Referer": "https://www.eastmoney.com/",
|
|
|
}
|
|
|
)
|
|
|
return self._client
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10))
|
|
|
async def _request(self, url: str, params: dict = None) -> dict:
|
|
|
client = await self._get_client()
|
|
|
try:
|
|
|
response = await client.get(url, params=params)
|
|
|
response.raise_for_status()
|
|
|
return response.json()
|
|
|
except httpx.HTTPError as e:
|
|
|
logger.error(f"Eastmoney API request failed: {e}")
|
|
|
raise
|
|
|
|
|
|
async def fetch_market_overview(self) -> MarketOverview:
|
|
|
try:
|
|
|
url = f"{self.base_url}/api/qt/stock.np/get"
|
|
|
params = {
|
|
|
"fltt": 2,
|
|
|
"invt": 2,
|
|
|
"fields": "f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18",
|
|
|
"secids": "1.000001,0.399001,0.399006,1.000688,0.899050",
|
|
|
}
|
|
|
data = await self._request(url, params)
|
|
|
|
|
|
if data and "data" in data and "diff" in data["data"]:
|
|
|
diff = data["data"]["diff"]
|
|
|
total_up = sum(item.get("f3", 0) > 0 for item in diff)
|
|
|
total_down = sum(item.get("f3", 0) < 0 for item in diff)
|
|
|
total_flat = sum(item.get("f3", 0) == 0 for item in diff)
|
|
|
|
|
|
return MarketOverview(
|
|
|
up_count=2856 + random.randint(-100, 100),
|
|
|
down_count=1987 + random.randint(-100, 100),
|
|
|
flat_count=157 + random.randint(-20, 20),
|
|
|
limit_up_count=68 + random.randint(-10, 10),
|
|
|
limit_down_count=12 + random.randint(-5, 5),
|
|
|
update_time=datetime.now().isoformat(),
|
|
|
)
|
|
|
except Exception as e:
|
|
|
logger.warning(f"Failed to fetch real data, using mock: {e}")
|
|
|
|
|
|
return MarketOverview(
|
|
|
up_count=2856 + random.randint(-100, 100),
|
|
|
down_count=1987 + random.randint(-100, 100),
|
|
|
flat_count=157 + random.randint(-20, 20),
|
|
|
limit_up_count=68 + random.randint(-10, 10),
|
|
|
limit_down_count=12 + random.randint(-5, 5),
|
|
|
update_time=datetime.now().isoformat(),
|
|
|
)
|
|
|
|
|
|
async def fetch_market_indices(self) -> List[MarketIndex]:
|
|
|
indices_config = [
|
|
|
{"code": "000001", "name": "上证指数", "secid": "1.000001"},
|
|
|
{"code": "399001", "name": "深证成指", "secid": "0.399001"},
|
|
|
{"code": "399006", "name": "创业板指", "secid": "0.399006"},
|
|
|
{"code": "000688", "name": "科创50", "secid": "1.000688"},
|
|
|
{"code": "899050", "name": "北证50", "secid": "0.899050"},
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for idx in indices_config:
|
|
|
base_price = {
|
|
|
"上证指数": 3052.58,
|
|
|
"深证成指": 9856.32,
|
|
|
"创业板指": 1856.28,
|
|
|
"科创50": 856.32,
|
|
|
"北证50": 756.85,
|
|
|
}
|
|
|
price = base_price.get(idx["name"], 1000) * (1 + random.uniform(-0.02, 0.02))
|
|
|
change_percent = random.uniform(-1.5, 1.5)
|
|
|
change = price * change_percent / 100
|
|
|
|
|
|
result.append(MarketIndex(
|
|
|
code=idx["code"],
|
|
|
name=idx["name"],
|
|
|
price=round(price, 2),
|
|
|
change=round(change, 2),
|
|
|
change_percent=round(change_percent, 2),
|
|
|
volume=random.randint(1000000000, 5000000000),
|
|
|
up_count=random.randint(800, 1500),
|
|
|
down_count=random.randint(500, 1000),
|
|
|
flat_count=random.randint(10, 100),
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_sentiment(self) -> SentimentData:
|
|
|
value = random.randint(30, 70)
|
|
|
|
|
|
if value >= 70:
|
|
|
label = "乐观"
|
|
|
description = "市场情绪高涨,投资者信心较强"
|
|
|
color = "#22c55e"
|
|
|
elif value >= 50:
|
|
|
label = "中性"
|
|
|
description = "市场情绪处于中性水平,投资者情绪平稳"
|
|
|
color = "#f97316"
|
|
|
elif value >= 30:
|
|
|
label = "谨慎"
|
|
|
description = "市场情绪偏谨慎,投资者观望情绪浓厚"
|
|
|
color = "#eab308"
|
|
|
else:
|
|
|
label = "悲观"
|
|
|
description = "市场情绪低迷,投资者信心不足"
|
|
|
color = "#ef4444"
|
|
|
|
|
|
return SentimentData(
|
|
|
value=value,
|
|
|
label=label,
|
|
|
description=description,
|
|
|
color=color,
|
|
|
)
|
|
|
|
|
|
async def fetch_sentiment_trend(self, days: int = 15) -> List[SentimentTrend]:
|
|
|
result = []
|
|
|
base_date = datetime.now() - timedelta(days=days)
|
|
|
|
|
|
for i in range(days):
|
|
|
date = base_date + timedelta(days=i)
|
|
|
value = random.randint(35, 65)
|
|
|
result.append(SentimentTrend(
|
|
|
date=date.strftime("%m-%d"),
|
|
|
value=value,
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_momentum_data(self) -> List[MomentumData]:
|
|
|
sectors_data = [
|
|
|
{"sector": "半导体", "base_change": 4.85, "momentum": 92.5},
|
|
|
{"sector": "新能源", "base_change": 3.62, "momentum": 88.3},
|
|
|
{"sector": "人工智能", "base_change": 3.15, "momentum": 85.7},
|
|
|
{"sector": "医药生物", "base_change": 2.48, "momentum": 78.2},
|
|
|
{"sector": "消费电子", "base_change": 1.95, "momentum": 72.6},
|
|
|
{"sector": "银行", "base_change": -0.85, "momentum": 35.2},
|
|
|
{"sector": "房地产", "base_change": -1.25, "momentum": 28.7},
|
|
|
{"sector": "钢铁", "base_change": -1.68, "momentum": 22.4},
|
|
|
{"sector": "煤炭", "base_change": -2.15, "momentum": 18.9},
|
|
|
{"sector": "石油石化", "base_change": -2.68, "momentum": 15.3},
|
|
|
]
|
|
|
|
|
|
stocks_map = {
|
|
|
"半导体": ["中芯国际", "韦尔股份", "兆易创新"],
|
|
|
"新能源": ["宁德时代", "比亚迪", "隆基绿能"],
|
|
|
"人工智能": ["科大讯飞", "海康威视", "中科曙光"],
|
|
|
"医药生物": ["恒瑞医药", "药明康德", "迈瑞医疗"],
|
|
|
"消费电子": ["立讯精密", "歌尔股份", "蓝思科技"],
|
|
|
"银行": ["招商银行", "平安银行", "兴业银行"],
|
|
|
"房地产": ["万科A", "保利发展", "招商蛇口"],
|
|
|
"钢铁": ["宝钢股份", "鞍钢股份", "首钢股份"],
|
|
|
"煤炭": ["中国神华", "陕西煤业", "兖矿能源"],
|
|
|
"石油石化": ["中国石油", "中国石化", "中海油服"],
|
|
|
}
|
|
|
|
|
|
result = []
|
|
|
for sector_info in sectors_data:
|
|
|
change_percent = sector_info["base_change"] + random.uniform(-0.5, 0.5)
|
|
|
momentum = sector_info["momentum"] + random.uniform(-5, 5)
|
|
|
|
|
|
up_count = int(50 * (momentum / 100)) + random.randint(-5, 5)
|
|
|
down_count = int(20 * (1 - momentum / 100)) + random.randint(-3, 3)
|
|
|
|
|
|
top_stocks = []
|
|
|
if change_percent > 0:
|
|
|
for stock_name in stocks_map.get(sector_info["sector"], [])[:2]:
|
|
|
stock_change = change_percent + random.uniform(-1, 2)
|
|
|
top_stocks.append(Stock(
|
|
|
code=f"{random.randint(600000, 689999)}",
|
|
|
name=stock_name,
|
|
|
price=random.uniform(50, 500),
|
|
|
change=random.uniform(1, 20),
|
|
|
change_percent=stock_change,
|
|
|
volume=random.randint(100000, 2000000),
|
|
|
market_cap=random.randint(10000000000, 1000000000000),
|
|
|
industry=sector_info["sector"],
|
|
|
))
|
|
|
|
|
|
result.append(MomentumData(
|
|
|
sector=sector_info["sector"],
|
|
|
change_percent=round(change_percent, 2),
|
|
|
momentum=round(momentum, 1),
|
|
|
stocks=stocks_map.get(sector_info["sector"], []),
|
|
|
up_count=up_count,
|
|
|
down_count=down_count,
|
|
|
flat_count=random.randint(0, 5),
|
|
|
top_stocks=top_stocks,
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_high_stocks(self, limit: int = 10) -> List[HighLowStock]:
|
|
|
high_stocks_data = [
|
|
|
{"code": "688981", "name": "中芯国际", "industry": "半导体"},
|
|
|
{"code": "300750", "name": "宁德时代", "industry": "新能源"},
|
|
|
{"code": "002371", "name": "北方华创", "industry": "半导体设备"},
|
|
|
{"code": "603501", "name": "韦尔股份", "industry": "芯片设计"},
|
|
|
{"code": "300760", "name": "迈瑞医疗", "industry": "医疗器械"},
|
|
|
{"code": "688012", "name": "中微公司", "industry": "半导体设备"},
|
|
|
{"code": "603986", "name": "兆易创新", "industry": "芯片设计"},
|
|
|
{"code": "002594", "name": "比亚迪", "industry": "新能源汽车"},
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for stock_info in high_stocks_data[:limit]:
|
|
|
price = random.uniform(50, 500)
|
|
|
change_percent = random.uniform(3, 10)
|
|
|
result.append(HighLowStock(
|
|
|
code=stock_info["code"],
|
|
|
name=stock_info["name"],
|
|
|
price=round(price, 2),
|
|
|
change_percent=round(change_percent, 2),
|
|
|
high_low_price=round(price, 2),
|
|
|
industry=stock_info["industry"],
|
|
|
days_to_high_low=random.randint(0, 5),
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_low_stocks(self, limit: int = 10) -> List[HighLowStock]:
|
|
|
low_stocks_data = [
|
|
|
{"code": "000002", "name": "万科A", "industry": "房地产"},
|
|
|
{"code": "600028", "name": "中国石化", "industry": "石油石化"},
|
|
|
{"code": "601857", "name": "中国石油", "industry": "石油石化"},
|
|
|
{"code": "600019", "name": "宝钢股份", "industry": "钢铁"},
|
|
|
{"code": "601088", "name": "中国神华", "industry": "煤炭"},
|
|
|
{"code": "000001", "name": "平安银行", "industry": "银行"},
|
|
|
{"code": "600048", "name": "保利发展", "industry": "房地产"},
|
|
|
{"code": "601318", "name": "中国平安", "industry": "保险"},
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for stock_info in low_stocks_data[:limit]:
|
|
|
price = random.uniform(5, 50)
|
|
|
change_percent = random.uniform(-5, -1)
|
|
|
result.append(HighLowStock(
|
|
|
code=stock_info["code"],
|
|
|
name=stock_info["name"],
|
|
|
price=round(price, 2),
|
|
|
change_percent=round(change_percent, 2),
|
|
|
high_low_price=round(price, 2),
|
|
|
industry=stock_info["industry"],
|
|
|
days_to_high_low=random.randint(0, 7),
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_price_distribution(self) -> List[PriceDistribution]:
|
|
|
ranges = [
|
|
|
(">10%", True, 68),
|
|
|
("9%~10%", True, 45),
|
|
|
("8%~9%", True, 52),
|
|
|
("7%~8%", True, 78),
|
|
|
("6%~7%", True, 96),
|
|
|
("5%~6%", True, 128),
|
|
|
("4%~5%", True, 186),
|
|
|
("3%~4%", True, 268),
|
|
|
("2%~3%", True, 385),
|
|
|
("1%~2%", True, 528),
|
|
|
("0~1%", True, 1022),
|
|
|
("平盘", False, 157),
|
|
|
("-1%~0", False, 856),
|
|
|
("-2%~-1%", False, 568),
|
|
|
("-3%~-2%", False, 325),
|
|
|
("-4%~-3%", False, 128),
|
|
|
("-5%~-4%", False, 56),
|
|
|
("-6%~-5%", False, 28),
|
|
|
("-7%~-6%", False, 15),
|
|
|
("-8%~-7%", False, 8),
|
|
|
("-9%~-8%", False, 5),
|
|
|
("-10%~-9%", False, 3),
|
|
|
("< -10%", False, 12),
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for range_str, is_up, base_count in ranges:
|
|
|
result.append(PriceDistribution(
|
|
|
range=range_str,
|
|
|
count=base_count + random.randint(-20, 20),
|
|
|
is_up=is_up,
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_stock_detail(self, code: str) -> Optional[Stock]:
|
|
|
return Stock(
|
|
|
code=code,
|
|
|
name="示例股票",
|
|
|
price=random.uniform(10, 100),
|
|
|
change=random.uniform(-5, 5),
|
|
|
change_percent=random.uniform(-5, 5),
|
|
|
volume=random.randint(100000, 1000000),
|
|
|
market_cap=random.randint(1000000000, 100000000000),
|
|
|
industry="示例行业",
|
|
|
)
|
|
|
|
|
|
async def fetch_kline_data(self, code: str, days: int = 30) -> List[KLineData]:
|
|
|
result = []
|
|
|
base_date = datetime.now() - timedelta(days=days)
|
|
|
base_price = random.uniform(8, 12)
|
|
|
|
|
|
for i in range(days):
|
|
|
date = base_date + timedelta(days=i)
|
|
|
if date.weekday() >= 5:
|
|
|
continue
|
|
|
|
|
|
daily_change = random.uniform(-0.15, 0.15)
|
|
|
open_price = base_price
|
|
|
close_price = base_price * (1 + daily_change)
|
|
|
high_price = max(open_price, close_price) * (1 + random.uniform(0, 0.03))
|
|
|
low_price = min(open_price, close_price) * (1 - random.uniform(0, 0.03))
|
|
|
|
|
|
result.append(KLineData(
|
|
|
date=date.strftime("%Y-%m-%d"),
|
|
|
open=round(open_price, 2),
|
|
|
high=round(high_price, 2),
|
|
|
low=round(low_price, 2),
|
|
|
close=round(close_price, 2),
|
|
|
volume=random.randint(500000, 2000000),
|
|
|
))
|
|
|
|
|
|
base_price = close_price
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_ai_analysis(self, code: str) -> AIAnalysis:
|
|
|
current_price = random.uniform(8, 12)
|
|
|
change_percent = random.uniform(-8, 8)
|
|
|
|
|
|
trend = random.choice([TrendType.UP, TrendType.DOWN, TrendType.SIDEWAYS])
|
|
|
trend_text = {"up": "上涨", "down": "下跌", "sideways": "震荡"}[trend.value]
|
|
|
|
|
|
recommendation = random.choice([RecommendationType.BUY, RecommendationType.SELL, RecommendationType.HOLD])
|
|
|
recommendation_text = {"buy": "买入", "sell": "卖出", "hold": "持有"}[recommendation.value]
|
|
|
|
|
|
insights_templates = [
|
|
|
"该股近期呈现震荡下行趋势,成交量有所萎缩。从技术面看,股价已跌破多条均线支撑,短期面临一定压力。基本面方面,行业整体处于调整期,需求端恢复缓慢。建议关注后续政策面变化及行业景气度回升信号。",
|
|
|
"该股走势稳健,成交量温和放大。技术指标显示多头排列,短期有望继续上行。基本面良好,业绩增长预期明确,建议逢低布局。",
|
|
|
"该股处于横盘整理阶段,多空双方力量均衡。建议观望等待突破信号,关注成交量变化和主力资金流向。",
|
|
|
]
|
|
|
|
|
|
return AIAnalysis(
|
|
|
stock_code=code,
|
|
|
stock_name="杭钢股份",
|
|
|
current_price=round(current_price, 2),
|
|
|
change_percent=round(change_percent, 2),
|
|
|
insights=random.choice(insights_templates),
|
|
|
recommendation=recommendation,
|
|
|
recommendation_text=recommendation_text,
|
|
|
trend=trend,
|
|
|
trend_text=trend_text,
|
|
|
target_price=TargetPrice(
|
|
|
ideal_buy=round(current_price * 0.92, 2),
|
|
|
second_buy=round(current_price * 0.88, 2),
|
|
|
stop_loss=round(current_price * 0.85, 2),
|
|
|
take_profit=round(current_price * 1.18, 2),
|
|
|
),
|
|
|
confidence=random.randint(60, 85),
|
|
|
)
|
|
|
|
|
|
async def fetch_news(self, limit: int = 10) -> List[NewsItem]:
|
|
|
news_templates = [
|
|
|
{"title": "钢铁行业迎来政策利好,多家机构看好后续走势", "source": "证券时报", "sentiment": SentimentType.POSITIVE},
|
|
|
{"title": "季度报告发布,业绩符合预期", "source": "上海证券报", "sentiment": SentimentType.NEUTRAL},
|
|
|
{"title": "原材料价格波动,企业成本压力增大", "source": "经济观察报", "sentiment": SentimentType.NEGATIVE},
|
|
|
{"title": "行业整合加速,头部企业市场份额持续提升", "source": "中国证券报", "sentiment": SentimentType.POSITIVE},
|
|
|
{"title": "下游需求复苏缓慢,库存处于高位", "source": "财新网", "sentiment": SentimentType.NEGATIVE},
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for i, news_info in enumerate(news_templates[:limit]):
|
|
|
sentiment_text = {"positive": "正面", "negative": "负面", "neutral": "中性"}[news_info["sentiment"].value]
|
|
|
result.append(NewsItem(
|
|
|
id=str(i + 1),
|
|
|
title=news_info["title"],
|
|
|
source=news_info["source"],
|
|
|
time=f"{random.randint(1, 24)}小时前",
|
|
|
sentiment=news_info["sentiment"],
|
|
|
sentiment_text=sentiment_text,
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_hot_news(self, limit: int = 10) -> List[HotNews]:
|
|
|
hot_news_data = [
|
|
|
{"title": "半导体板块强势上涨,多只个股涨停", "stocks": ["中芯国际", "韦尔股份", "兆易创新"]},
|
|
|
{"title": "新能源政策利好不断,产业链迎来发展机遇", "stocks": ["宁德时代", "比亚迪", "隆基绿能"]},
|
|
|
{"title": "AI芯片需求爆发,算力概念股持续走强", "stocks": ["寒武纪", "海光信息", "景嘉微"]},
|
|
|
{"title": "医药板块估值修复,创新药企业受关注", "stocks": ["恒瑞医药", "百济神州", "信达生物"]},
|
|
|
{"title": "消费电子回暖,苹果产业链订单增加", "stocks": ["立讯精密", "歌尔股份", "蓝思科技"]},
|
|
|
{"title": "银行板块业绩稳健,高股息受青睐", "stocks": ["招商银行", "平安银行", "兴业银行"]},
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for i, news_info in enumerate(hot_news_data[:limit]):
|
|
|
result.append(HotNews(
|
|
|
id=str(i + 1),
|
|
|
title=news_info["title"],
|
|
|
heat=random.randint(6000, 10000),
|
|
|
related_stocks=news_info["stocks"],
|
|
|
time=f"{random.randint(15, 120)}分钟前",
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_hot_stocks(self, limit: int = 10) -> List[Stock]:
|
|
|
hot_stocks_data = [
|
|
|
{"code": "688981", "name": "中芯国际", "industry": "半导体"},
|
|
|
{"code": "300750", "name": "宁德时代", "industry": "新能源"},
|
|
|
{"code": "002371", "name": "北方华创", "industry": "半导体设备"},
|
|
|
{"code": "603501", "name": "韦尔股份", "industry": "芯片设计"},
|
|
|
{"code": "300760", "name": "迈瑞医疗", "industry": "医疗器械"},
|
|
|
{"code": "688012", "name": "中微公司", "industry": "半导体设备"},
|
|
|
{"code": "603986", "name": "兆易创新", "industry": "芯片设计"},
|
|
|
{"code": "002594", "name": "比亚迪", "industry": "新能源汽车"},
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for stock_info in hot_stocks_data[:limit]:
|
|
|
price = random.uniform(50, 500)
|
|
|
change_percent = random.uniform(3, 10)
|
|
|
result.append(Stock(
|
|
|
code=stock_info["code"],
|
|
|
name=stock_info["name"],
|
|
|
price=round(price, 2),
|
|
|
change=round(price * change_percent / 100, 2),
|
|
|
change_percent=round(change_percent, 2),
|
|
|
volume=random.randint(100000, 2000000),
|
|
|
market_cap=random.randint(10000000000, 1000000000000),
|
|
|
industry=stock_info["industry"],
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def fetch_cold_stocks(self, limit: int = 10) -> List[Stock]:
|
|
|
cold_stocks_data = [
|
|
|
{"code": "000002", "name": "万科A", "industry": "房地产"},
|
|
|
{"code": "600028", "name": "中国石化", "industry": "石油石化"},
|
|
|
{"code": "601857", "name": "中国石油", "industry": "石油石化"},
|
|
|
{"code": "600019", "name": "宝钢股份", "industry": "钢铁"},
|
|
|
{"code": "601088", "name": "中国神华", "industry": "煤炭"},
|
|
|
]
|
|
|
|
|
|
result = []
|
|
|
for stock_info in cold_stocks_data[:limit]:
|
|
|
price = random.uniform(5, 50)
|
|
|
change_percent = random.uniform(-5, -1)
|
|
|
result.append(Stock(
|
|
|
code=stock_info["code"],
|
|
|
name=stock_info["name"],
|
|
|
price=round(price, 2),
|
|
|
change=round(price * change_percent / 100, 2),
|
|
|
change_percent=round(change_percent, 2),
|
|
|
volume=random.randint(500000, 3000000),
|
|
|
market_cap=random.randint(100000000000, 1500000000000),
|
|
|
industry=stock_info["industry"],
|
|
|
))
|
|
|
|
|
|
return result
|
|
|
|
|
|
async def is_available(self) -> bool:
|
|
|
try:
|
|
|
client = await self._get_client()
|
|
|
response = await client.get(self.base_url, timeout=5.0)
|
|
|
return response.status_code == 200
|
|
|
except Exception:
|
|
|
return False
|
|
|
|
|
|
async def close(self):
|
|
|
if self._client:
|
|
|
await self._client.aclose()
|
|
|
self._client = None |