1
This commit is contained in:
parent
a6e253a0c5
commit
7d0ede2912
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -7,7 +7,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from app.engine.screener import run_screening
|
from app.engine.screener import run_screening
|
||||||
from app.data.models import Recommendation, MarketTemperature, SectorInfo
|
from app.data.models import Recommendation, MarketTemperature, SectorInfo
|
||||||
from app.db.database import get_db
|
from app.db.database import get_db
|
||||||
@ -277,7 +277,6 @@ async def get_latest_sectors() -> list[SectorInfo]:
|
|||||||
|
|
||||||
async def get_recommendation_history(days: int = 7) -> list[dict]:
|
async def get_recommendation_history(days: int = 7) -> list[dict]:
|
||||||
"""获取历史推荐记录,按日期分组返回"""
|
"""获取历史推荐记录,按日期分组返回"""
|
||||||
from datetime import timedelta
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
start = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
|
start = (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
|
||||||
@ -427,6 +426,7 @@ async def _save_to_db(result: dict):
|
|||||||
|
|
||||||
# 保存推荐(按 ts_code 清除当日旧记录,避免同一天多次扫描产生重复)
|
# 保存推荐(按 ts_code 清除当日旧记录,避免同一天多次扫描产生重复)
|
||||||
today_str = datetime.now().strftime("%Y-%m-%d")
|
today_str = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
now_ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
saved_count = 0
|
saved_count = 0
|
||||||
for rec in result.get("recommendations", []):
|
for rec in result.get("recommendations", []):
|
||||||
if rec.score < 60:
|
if rec.score < 60:
|
||||||
@ -458,6 +458,7 @@ async def _save_to_db(result: dict):
|
|||||||
entry_signal_type=rec.entry_signal_type,
|
entry_signal_type=rec.entry_signal_type,
|
||||||
llm_score=rec.llm_score,
|
llm_score=rec.llm_score,
|
||||||
scan_session=rec.scan_session,
|
scan_session=rec.scan_session,
|
||||||
|
created_at=now_ts,
|
||||||
)
|
)
|
||||||
await db.execute(stmt)
|
await db.execute(stmt)
|
||||||
saved_count += 1
|
saved_count += 1
|
||||||
|
|||||||
@ -653,22 +653,22 @@ async def _build_recommendations(
|
|||||||
rec.llm_analysis = llm_data.get("analysis", "")
|
rec.llm_analysis = llm_data.get("analysis", "")
|
||||||
|
|
||||||
# LLM 信号强度转换为分数调整
|
# LLM 信号强度转换为分数调整
|
||||||
|
# 调整幅度温和,保底不低于 60,避免推荐被过滤掉
|
||||||
strength = llm_data.get("strength", "中")
|
strength = llm_data.get("strength", "中")
|
||||||
llm_signal = llm_data.get("signal", "HOLD")
|
llm_signal = llm_data.get("signal", "HOLD")
|
||||||
|
|
||||||
# 基础调整:量化评分 * 调整系数
|
|
||||||
if llm_signal == "SKIP":
|
if llm_signal == "SKIP":
|
||||||
adjustment = 0.50
|
# 降分但保底 60,排序靠后但不消失
|
||||||
|
rec.score = max(60, round(rec.score - 15, 1))
|
||||||
elif llm_signal == "HOLD":
|
elif llm_signal == "HOLD":
|
||||||
adjustment = 0.85
|
rec.score = max(60, round(rec.score - 5, 1))
|
||||||
elif llm_signal == "BUY" and strength == "强":
|
elif llm_signal == "BUY" and strength == "强":
|
||||||
adjustment = 1.15
|
rec.score = round(rec.score + 10, 1)
|
||||||
elif llm_signal == "BUY" and strength == "中":
|
elif llm_signal == "BUY" and strength == "中":
|
||||||
adjustment = 1.05
|
rec.score = round(rec.score + 5, 1)
|
||||||
else: # BUY + 弱
|
else: # BUY + 弱
|
||||||
adjustment = 1.00
|
pass # 不调整
|
||||||
|
|
||||||
rec.score = round(rec.score * adjustment, 1)
|
|
||||||
rec.level = _score_to_level(rec.score)
|
rec.level = _score_to_level(rec.score)
|
||||||
|
|
||||||
# 用 LLM 给出的价格替代硬编码价格
|
# 用 LLM 给出的价格替代硬编码价格
|
||||||
|
|||||||
Binary file not shown.
@ -1,25 +1,3 @@
|
|||||||
{
|
{
|
||||||
"pages": {
|
"pages": {}
|
||||||
"/(public)/page": [
|
|
||||||
"static/chunks/webpack.js",
|
|
||||||
"static/chunks/main-app.js",
|
|
||||||
"static/chunks/app/(public)/page.js"
|
|
||||||
],
|
|
||||||
"/(public)/layout": [
|
|
||||||
"static/chunks/webpack.js",
|
|
||||||
"static/chunks/main-app.js",
|
|
||||||
"static/chunks/app/(public)/layout.js"
|
|
||||||
],
|
|
||||||
"/layout": [
|
|
||||||
"static/chunks/webpack.js",
|
|
||||||
"static/chunks/main-app.js",
|
|
||||||
"static/css/app/layout.css",
|
|
||||||
"static/chunks/app/layout.js"
|
|
||||||
],
|
|
||||||
"/_not-found/page": [
|
|
||||||
"static/chunks/webpack.js",
|
|
||||||
"static/chunks/main-app.js",
|
|
||||||
"static/chunks/app/_not-found/page.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -8,10 +8,7 @@
|
|||||||
"static/development/_buildManifest.js",
|
"static/development/_buildManifest.js",
|
||||||
"static/development/_ssgManifest.js"
|
"static/development/_ssgManifest.js"
|
||||||
],
|
],
|
||||||
"rootMainFiles": [
|
"rootMainFiles": [],
|
||||||
"static/chunks/webpack.js",
|
|
||||||
"static/chunks/main-app.js"
|
|
||||||
],
|
|
||||||
"pages": {
|
"pages": {
|
||||||
"/_app": []
|
"/_app": []
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,4 +1 @@
|
|||||||
{
|
{}
|
||||||
"/_not-found/page": "app/_not-found/page.js",
|
|
||||||
"/(public)/page": "app/(public)/page.js"
|
|
||||||
}
|
|
||||||
@ -5,10 +5,7 @@ self.__BUILD_MANIFEST = {
|
|||||||
"devFiles": [],
|
"devFiles": [],
|
||||||
"ampDevFiles": [],
|
"ampDevFiles": [],
|
||||||
"lowPriorityFiles": [],
|
"lowPriorityFiles": [],
|
||||||
"rootMainFiles": [
|
"rootMainFiles": [],
|
||||||
"static/chunks/webpack.js",
|
|
||||||
"static/chunks/main-app.js"
|
|
||||||
],
|
|
||||||
"pages": {
|
"pages": {
|
||||||
"/_app": []
|
"/_app": []
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"node": {},
|
"node": {},
|
||||||
"edge": {},
|
"edge": {},
|
||||||
"encryptionKey": "SjG27okSsVCMkYFxh9VzL5dGKrpz1m5ZqXbmUB/f6XQ="
|
"encryptionKey": "TvpNgjmx7YLTcpuR9/rx1RyNnHAsQtr+fCBhzhbdwwo="
|
||||||
}
|
}
|
||||||
@ -1,215 +0,0 @@
|
|||||||
/*
|
|
||||||
* ATTENTION: An "eval-source-map" devtool has been used.
|
|
||||||
* This devtool is neither made for production nor for readable output files.
|
|
||||||
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
|
|
||||||
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
|
|
||||||
* or disable the default devtool with "devtool: false".
|
|
||||||
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
|
|
||||||
*/
|
|
||||||
/******/ (() => { // webpackBootstrap
|
|
||||||
/******/ "use strict";
|
|
||||||
/******/ var __webpack_modules__ = ({});
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ // The module cache
|
|
||||||
/******/ var __webpack_module_cache__ = {};
|
|
||||||
/******/
|
|
||||||
/******/ // The require function
|
|
||||||
/******/ function __webpack_require__(moduleId) {
|
|
||||||
/******/ // Check if module is in cache
|
|
||||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
||||||
/******/ if (cachedModule !== undefined) {
|
|
||||||
/******/ return cachedModule.exports;
|
|
||||||
/******/ }
|
|
||||||
/******/ // Create a new module (and put it into the cache)
|
|
||||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
||||||
/******/ id: moduleId,
|
|
||||||
/******/ loaded: false,
|
|
||||||
/******/ exports: {}
|
|
||||||
/******/ };
|
|
||||||
/******/
|
|
||||||
/******/ // Execute the module function
|
|
||||||
/******/ var threw = true;
|
|
||||||
/******/ try {
|
|
||||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
||||||
/******/ threw = false;
|
|
||||||
/******/ } finally {
|
|
||||||
/******/ if(threw) delete __webpack_module_cache__[moduleId];
|
|
||||||
/******/ }
|
|
||||||
/******/
|
|
||||||
/******/ // Flag the module as loaded
|
|
||||||
/******/ module.loaded = true;
|
|
||||||
/******/
|
|
||||||
/******/ // Return the exports of the module
|
|
||||||
/******/ return module.exports;
|
|
||||||
/******/ }
|
|
||||||
/******/
|
|
||||||
/******/ // expose the modules object (__webpack_modules__)
|
|
||||||
/******/ __webpack_require__.m = __webpack_modules__;
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/ /* webpack/runtime/compat get default export */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
||||||
/******/ __webpack_require__.n = (module) => {
|
|
||||||
/******/ var getter = module && module.__esModule ?
|
|
||||||
/******/ () => (module['default']) :
|
|
||||||
/******/ () => (module);
|
|
||||||
/******/ __webpack_require__.d(getter, { a: getter });
|
|
||||||
/******/ return getter;
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/create fake namespace object */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
|
|
||||||
/******/ var leafPrototypes;
|
|
||||||
/******/ // create a fake namespace object
|
|
||||||
/******/ // mode & 1: value is a module id, require it
|
|
||||||
/******/ // mode & 2: merge all properties of value into the ns
|
|
||||||
/******/ // mode & 4: return value when already ns object
|
|
||||||
/******/ // mode & 16: return value when it's Promise-like
|
|
||||||
/******/ // mode & 8|1: behave like require
|
|
||||||
/******/ __webpack_require__.t = function(value, mode) {
|
|
||||||
/******/ if(mode & 1) value = this(value);
|
|
||||||
/******/ if(mode & 8) return value;
|
|
||||||
/******/ if(typeof value === 'object' && value) {
|
|
||||||
/******/ if((mode & 4) && value.__esModule) return value;
|
|
||||||
/******/ if((mode & 16) && typeof value.then === 'function') return value;
|
|
||||||
/******/ }
|
|
||||||
/******/ var ns = Object.create(null);
|
|
||||||
/******/ __webpack_require__.r(ns);
|
|
||||||
/******/ var def = {};
|
|
||||||
/******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
|
|
||||||
/******/ for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {
|
|
||||||
/******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
|
|
||||||
/******/ }
|
|
||||||
/******/ def['default'] = () => (value);
|
|
||||||
/******/ __webpack_require__.d(ns, def);
|
|
||||||
/******/ return ns;
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/define property getters */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // define getter functions for harmony exports
|
|
||||||
/******/ __webpack_require__.d = (exports, definition) => {
|
|
||||||
/******/ for(var key in definition) {
|
|
||||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
||||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
||||||
/******/ }
|
|
||||||
/******/ }
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/ensure chunk */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ __webpack_require__.f = {};
|
|
||||||
/******/ // This file contains only the entry chunk.
|
|
||||||
/******/ // The chunk loading function for additional chunks
|
|
||||||
/******/ __webpack_require__.e = (chunkId) => {
|
|
||||||
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
|
|
||||||
/******/ __webpack_require__.f[key](chunkId, promises);
|
|
||||||
/******/ return promises;
|
|
||||||
/******/ }, []));
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/get javascript chunk filename */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // This function allow to reference async chunks and sibling chunks for the entrypoint
|
|
||||||
/******/ __webpack_require__.u = (chunkId) => {
|
|
||||||
/******/ // return url for filenames based on template
|
|
||||||
/******/ return "" + chunkId + ".js";
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/getFullHash */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ __webpack_require__.h = () => ("9f25f13e592044c8")
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/make namespace object */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // define __esModule on exports
|
|
||||||
/******/ __webpack_require__.r = (exports) => {
|
|
||||||
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
||||||
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
||||||
/******/ }
|
|
||||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/node module decorator */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ __webpack_require__.nmd = (module) => {
|
|
||||||
/******/ module.paths = [];
|
|
||||||
/******/ if (!module.children) module.children = [];
|
|
||||||
/******/ return module;
|
|
||||||
/******/ };
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/startup entrypoint */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ __webpack_require__.X = (result, chunkIds, fn) => {
|
|
||||||
/******/ // arguments: chunkIds, moduleId are deprecated
|
|
||||||
/******/ var moduleId = chunkIds;
|
|
||||||
/******/ if(!fn) chunkIds = result, fn = () => (__webpack_require__(__webpack_require__.s = moduleId));
|
|
||||||
/******/ chunkIds.map(__webpack_require__.e, __webpack_require__)
|
|
||||||
/******/ var r = fn();
|
|
||||||
/******/ return r === undefined ? result : r;
|
|
||||||
/******/ }
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/******/ /* webpack/runtime/require chunk loading */
|
|
||||||
/******/ (() => {
|
|
||||||
/******/ // no baseURI
|
|
||||||
/******/
|
|
||||||
/******/ // object to store loaded chunks
|
|
||||||
/******/ // "1" means "loaded", otherwise not loaded yet
|
|
||||||
/******/ var installedChunks = {
|
|
||||||
/******/ "webpack-runtime": 1
|
|
||||||
/******/ };
|
|
||||||
/******/
|
|
||||||
/******/ // no on chunks loaded
|
|
||||||
/******/
|
|
||||||
/******/ var installChunk = (chunk) => {
|
|
||||||
/******/ var moreModules = chunk.modules, chunkIds = chunk.ids, runtime = chunk.runtime;
|
|
||||||
/******/ for(var moduleId in moreModules) {
|
|
||||||
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
|
|
||||||
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
|
|
||||||
/******/ }
|
|
||||||
/******/ }
|
|
||||||
/******/ if(runtime) runtime(__webpack_require__);
|
|
||||||
/******/ for(var i = 0; i < chunkIds.length; i++)
|
|
||||||
/******/ installedChunks[chunkIds[i]] = 1;
|
|
||||||
/******/
|
|
||||||
/******/ };
|
|
||||||
/******/
|
|
||||||
/******/ // require() chunk loading for javascript
|
|
||||||
/******/ __webpack_require__.f.require = (chunkId, promises) => {
|
|
||||||
/******/ // "1" is the signal for "already loaded"
|
|
||||||
/******/ if(!installedChunks[chunkId]) {
|
|
||||||
/******/ if("webpack-runtime" != chunkId) {
|
|
||||||
/******/ installChunk(require("./" + __webpack_require__.u(chunkId)));
|
|
||||||
/******/ } else installedChunks[chunkId] = 1;
|
|
||||||
/******/ }
|
|
||||||
/******/ };
|
|
||||||
/******/
|
|
||||||
/******/ module.exports = __webpack_require__;
|
|
||||||
/******/ __webpack_require__.C = installChunk;
|
|
||||||
/******/
|
|
||||||
/******/ // no HMR
|
|
||||||
/******/
|
|
||||||
/******/ // no HMR manifest
|
|
||||||
/******/ })();
|
|
||||||
/******/
|
|
||||||
/************************************************************************/
|
|
||||||
/******/
|
|
||||||
/******/
|
|
||||||
/******/ })()
|
|
||||||
;
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user