如何用Django查询收盘价高于去年同日的股票数据
解决方案
首先假设你的Django模型结构如下(如果实际字段不同,可对应调整):
from django.db import models class Ticker(models.Model): symbol = models.CharField(max_length=10, unique=True) # 其他字段如名称、行业等 class TickerPrice(models.Model): ticker = models.ForeignKey(Ticker, on_delete=models.CASCADE, related_name='prices') date = models.DateField() close = models.DecimalField(max_digits=10, decimal_places=2) # 对应需求中的收盘价字段 class Meta: unique_together = ('ticker', 'date') # 确保同股票同日期仅一条记录
要筛选出收盘价高于去年同日的股票数据,可利用Django的Subquery和OuterRef实现关联子查询,具体代码如下:
from django.db.models import Subquery, OuterRef, F, Value from django.db.models.fields import DecimalField, DateField from django.db.models.functions import ExpressionWrapper # 构造子查询:获取当前记录对应股票的去年同日收盘价 last_year_price_subquery = TickerPrice.objects.filter( ticker=OuterRef('ticker'), # 通过表达式实现日期减一年,适配多数数据库规则 date=ExpressionWrapper( F('date') - ExpressionWrapper(Value('1 year'), output_field=models.DurationField()), output_field=DateField() ) ).values('close')[:1] # 筛选符合条件的记录 qualified_prices = TickerPrice.objects.annotate( last_year_close=Subquery(last_year_price_subquery, output_field=DecimalField()) ).filter( close__gte=F('last_year_close'), last_year_close__isnull=False # 排除去年同日无数据的记录 )
关键逻辑说明
- 子查询关联:通过
OuterRef引用外层查询的ticker和date字段,精准匹配同一只股票的去年同日价格记录。 - 日期处理:用
ExpressionWrapper实现日期减一年的操作,适配多数数据库的日期运算规则。 - 筛选条件:通过
annotate添加去年收盘价字段后,直接比较当前收盘价与去年收盘价,同时过滤掉去年无对应数据的记录(避免空值干扰)。
特殊情况处理(闰年2月29日)
如果需要处理闰年2月29日的情况(比如2024-02-29的去年同日是2023-02-28),不同数据库有不同适配方式:
- PostgreSQL:上述代码的日期减法会自动将2024-02-29转为2023-02-28,无需额外处理。
- MySQL:改用
RawSQL实现日期调整:last_year_price_subquery = TickerPrice.objects.filter( ticker=OuterRef('ticker'), date=models.RawSQL("DATE_SUB(date, INTERVAL 1 YEAR)", []) ).values('close')[:1] - SQLite:使用SQLite原生日期函数:
date=models.RawSQL("date(date, '-1 year')", [])
内容的提问来源于stack exchange,提问作者user3874862
相关产品推荐
相关产品推荐

