[odoo18】集成echarts-画出股票收盘价走势图

odoo18集成echarts

1.下载echarts.min.js

ECharts的官方下载网址:https://echarts.apache.org/zh/download.html

2.目录结构

在这里插入图片描述

3.通过tdx获取数据

    def get_k_data(self, code, start, end):
        """
        日线级别k线获取函数
        """
        for retry in range(3):
            try:
                if self.api.connect(self.ip, int(self.port)):
                    df = self.api.get_k_data(code, start, end)
                    return df.to_dict('records') or []
            except Exception as e:
                time.sleep(3)
        return []

在这里插入图片描述

4.引用echarts.min.js

manifest.py

'assets': {
   'web.assets_backend': [
        'quantization_base/static/lib/**/*',
        'quantization_base/static/src/**/*',
    ]
},

5.前端代码实现

stock_pe_report.js

/** @odoo-module **/

import {registry} from "@web/core/registry";
import {Component, onMounted, useRef} from "@odoo/owl";

export class PeChart extends Component {
    static template = "quantization_base.StockPeReport";

    setup() {
        this.date_list = this.props.action.params.date_list || {};
        this.data_list = this.props.action.params.data_list || [];
        this.peContainerRef = useRef("PeContainer"); // 通过 ref 获取 DOM 元素
        onMounted(() => this.initECharts()); // 确保 DOM 已挂载
    }

    initECharts() {
        // 确保 DOM 元素存在
        if (!this.peContainerRef.el) return;
        // 初始化图表
        // 基于准备好的 DOM,初始化 echarts 实例
        var myChart = echarts.init(this.peContainerRef.el);
        // 指定图表的配置项和数据
        var option = {
            title: {
                text: 'PE曲线图'
            },
            tooltip: {
                trigger: 'axis'
            },
            legend: {
                data: ['收盘价', 'PE10', 'PE20', 'PB30', 'PB40', 'PB50'],
                bottom: 15, // 设置图例距离容器底部的距离
                orient: 'horizontal' // 设置图例为水平排列
            },
            xAxis: {
                type: 'category',
                boundaryGap: false,
                data: this.date_list
            },
            yAxis: {
                type: 'value'
            },
            series: this.data_list
            // 注意:如果你没有特定的颜色要求,可以移除每个 series 中的 itemStyle 配置。
        };
        myChart.setOption(option);
    }
}

registry.category("actions").add("stock_pe_report", PeChart);
}

stock_pe_report.xml

<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
    <t t-name="quantization_base.StockPeReport">
        <div id="pe-container" t-ref="PeContainer" style="width: 600px;height:400px;">
        </div>
    </t>
</templates>

菜单调用

stock_pe_report.xml

<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data>
        <record id="form_stock_pe_report" model="ir.ui.view">
            <field name="name">Stock PE Report</field>
            <field name="model">stock.pe.report</field>
            <field name="arch" type="xml">
                <form>
                    <group>
                        <field name="stock_id" domain="[('finance_ids', '!=', False)]"/>
                    </group>
                    <footer>
                        <button string="取消" class="oe_link" special="cancel"/>
                        or
                        <button name="action_open" string="确定" type="object" default_focus="1"
                                class="oe_highlight"/>
                    </footer>
                </form>
            </field>
        </record>

        <record id="action_stock_pe_report" model="ir.actions.act_window">
            <field name="name">PE/PB报表</field>
            <field name="res_model">stock.pe.report</field>
            <field name="view_mode">form</field>
            <field name="view_id" ref="form_stock_pe_report"/>
            <field name="target">new</field>
        </record>
    </data>
</odoo>

stock_pe_report.py

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import UserError
from datetime import datetime, timedelta
from odoo.tools import groupby
from operator import itemgetter


class StockPeReport(models.TransientModel):
    _name = 'stock.pe.report'
    _description = "Stock Pe Report"

    stock_id = fields.Many2one('equity.stock', string="股票", required=True)
    pe_pb_choice = fields.Selection([
        ('pe', '市盈率'),
        ('pb', '市净率'),
    ], string="P/E或P/B", default='pe', required=True)

    def get_stock_trend_ids(self):
        """
        获取股票数据
        """
        domain = [
            ('stock_id', '=', self.stock_id.id),
        ]
        stock_trend_ids = self.env['stock.trend'].search(domain, order='trend_date')
        return stock_trend_ids

    def action_open(self):
        """
        打开报表
        """
        # 打印表行
        if self.pe_pb_choice != 'pe':
            raise UserError('暂不支持P/B报表')
        date_list, data_list = self.get_lines()
        return {
            'type': 'ir.actions.client',
            'tag': 'stock_pe_report',
            'name': _('PE报表'),
            'params': {
                'date_list': date_list,
                'data_list': data_list
            }
        }

    def get_lines(self):
        """
        data: ['收盘价', 'PE10', 'PE20', 'PB30', 'PB40', 'PB50'],
        {
            name: '收盘价',
            type: 'line',
            data: [120, 132, 101, 134, 90, 230]
        },
        """
        self.ensure_one()
        stock_trend_ids = self.get_stock_trend_ids()
        if not stock_trend_ids:
            return
        date_list = []
        close_trend_data = {
            'name': '收盘价',
            'type': 'line',
            'data': []
        }
        pe_10_trend_data = {
            'name': 'PE10',
            'type': 'line',
            'data': []
        }
        pe_20_trend_data = {
            'name': 'PE20',
            'type': 'line',
            'data': []
        }
        pe_30_trend_data = {
            'name': 'PB30',
            'type': 'line',
            'data': []
        }
        pe_40_trend_data = {
            'name': 'PB40',
            'type': 'line',
            'data': []
        }
        pe_50_trend_data = {
            'name': 'PB50',
            'type': 'line',
            'data': []
        }
        for trend_id in stock_trend_ids:
            net_profit = self.stock_id.finance_ids[0].net_profit
            shareholding_equity = self.stock_id.finance_ids[0].shareholding_equity
            if shareholding_equity == 0:
                continue
            date_list.append(trend_id.trend_date.strftime('%Y-%m-%d'))
            close_price = trend_id.close
            pe_10_price = 10 * net_profit / shareholding_equity
            pe_20_price = 20 * net_profit / shareholding_equity
            pe_30_price = 30 * net_profit / shareholding_equity
            pe_40_price = 40 * net_profit / shareholding_equity
            pe_50_price = 50 * net_profit / shareholding_equity

            close_trend_data['data'].append(close_price)
            pe_10_trend_data['data'].append(pe_10_price)
            pe_20_trend_data['data'].append(pe_20_price)
            pe_30_trend_data['data'].append(pe_30_price)
            pe_40_trend_data['data'].append(pe_40_price)
            pe_50_trend_data['data'].append(pe_50_price)
        return date_list, [close_trend_data, pe_10_trend_data, pe_20_trend_data, pe_30_trend_data, pe_40_trend_data, pe_50_trend_data]

ui_menu_views.xml

<menuitem action="action_stock_pe_report"
                  name="Pe/Pb报表"
                  id="menu_stock_pe_report"
                  parent="menu_stock_report_root"
                  sequence="5"/>

6.效果展示

在这里插入图片描述

7.学习总结

1、echarts在初始化时需要引入echarts.min.js,为了保证echarts被先引入,将lib放到最前面。

'assets': {
    'web.assets_backend': [
        'quantization_base/static/lib/**/*',
        'quantization_base/static/src/**/*',
    ]
},

2、echarts在初始化时需要指定dom父节点,因此需要在onMounted中去实现初始化echarts
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值