| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- // 融资需求与货币供给 — 图表配置
- import { palette as C } from './data'
- const tipOpt = {
- backgroundColor: 'rgba(12,43,94,.94)',
- borderWidth: 0,
- textStyle: { color: '#fff', fontSize: 12 },
- padding: [8, 12],
- extraCssText: 'box-shadow:0 6px 18px rgba(12,43,94,.3);border-radius:6px;',
- }
- function axisStyle(opts = {}) {
- return {
- axisLine: { lineStyle: { color: '#E4E9F2' } },
- axisTick: { show: false },
- axisLabel: { color: C.mut, fontSize: 11 },
- splitLine: { lineStyle: { color: '#F2F5FA', type: 'dashed' } },
- ...opts,
- }
- }
- const sliceYM = (s) => s.map((x) => String(x[0]).slice(2, 7))
- // ============== 图1 社融增速和M2增速 ==============
- export function tsfM2LineOption(m2Series, tsfSeries) {
- const m2Map = new Map(m2Series.map((x) => [String(x[0]).slice(0, 10), x[1]]))
- const tsfMap = new Map(tsfSeries.map((x) => [String(x[0]).slice(0, 10), x[1]]))
- const cats = tsfSeries.map((x) => String(x[0]).slice(2, 7))
- return {
- tooltip: { ...tipOpt, trigger: 'axis' },
- legend: {
- data: ['社融存量同比', 'M2 同比'],
- top: 6, textStyle: { color: C.mut, fontSize: 11 }, itemWidth: 14, itemHeight: 8,
- },
- grid: { top: 32, left: 46, right: 18, bottom: 28 },
- xAxis: { type: 'category', data: cats, ...axisStyle({ axisLabel: { color: C.mut, fontSize: 10, hideOverlap: true } }) },
- yAxis: { type: 'value', name: '%', ...axisStyle() },
- series: [
- {
- name: '社融存量同比',
- type: 'line', smooth: true, showSymbol: false, symbol: 'circle', symbolSize: 5,
- data: tsfSeries.map((x) => x[1]),
- lineStyle: { color: C.brandD, width: 2.4 },
- itemStyle: { color: C.brandD },
- areaStyle: {
- type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
- colorStops: [{ offset: 0, color: 'rgba(14,58,150,.14)' }, { offset: 1, color: 'rgba(14,58,150,0)' }],
- },
- markLine: { symbol: ['none', 'none'], data: [{ yAxis: 0, lineStyle: { color: C.faint, type: 'dashed', width: 1 } }], label: { show: false } },
- },
- {
- name: 'M2 同比',
- type: 'line', smooth: true, showSymbol: false, symbol: 'circle', symbolSize: 5,
- data: cats.map((_, i) => {
- const full = tsfSeries[i][0]
- return m2Map.get(String(full).slice(0, 10)) ?? null
- }),
- lineStyle: { color: C.warn, width: 2.2 },
- itemStyle: { color: C.warn },
- markLine: { symbol: ['none', 'none'], data: [{ yAxis: 0, lineStyle: { color: C.faint, type: 'dashed', width: 1 } }], label: { show: false } },
- },
- ],
- }
- }
- // ============== 图2 社融分项结构 ==============
- const TSF_COLORS = ['#1552D0', '#7A4FCB', '#5B8DEF', '#0E3A96', '#E8912D', '#3DB389', '#E13B3B', '#6B7A96']
- const TSF_LEGEND = ['人民币贷款', '外币贷款', '委托贷款', '信托贷款', '未贴现银行承兑汇票', '企业债券融资', '股票融资', '政府债券']
- export function tsfStructureOption(d) {
- const cats = (d.categories || []).map((x) => String(x).slice(2, 7))
- const series = [
- { key: 'rmbLoan', name: '人民币贷款' },
- { key: 'fxLoan', name: '外币贷款' },
- { key: 'wtLoan', name: '委托贷款' },
- { key: 'xtxLoan', name: '信托贷款' },
- { key: 'wtzbpj', name: '未贴现银行承兑汇票' },
- { key: 'corpBond', name: '企业债券融资' },
- { key: 'equity', name: '股票融资' },
- { key: 'govBond', name: '政府债券' },
- ]
- return {
- tooltip: { ...tipOpt, trigger: 'axis', axisPointer: { type: 'shadow' } },
- legend: {
- data: TSF_LEGEND,
- top: 6, type: 'scroll', textStyle: { color: C.mut, fontSize: 11 }, itemWidth: 14, itemHeight: 8,
- },
- grid: { top: 32, left: 56, right: 18, bottom: 28 },
- xAxis: { type: 'category', data: cats, ...axisStyle({ axisLabel: { color: C.mut, fontSize: 10, hideOverlap: true } }) },
- yAxis: { type: 'value', name: '亿元', ...axisStyle() },
- series: series.map((s, idx) => ({
- name: s.name, type: 'bar', stack: 'tsf', data: d[s.key] || [],
- itemStyle: { color: TSF_COLORS[idx], borderRadius: idx === 0 ? [3, 3, 0, 0] : 0 },
- barWidth: 18,
- })),
- }
- }
- // ============== 图3 信贷分项结构 ==============
- const LOAN_COLORS = ['#1552D0', '#E8912D', '#0E3A96', '#7A4FCB', '#189A65']
- const LOAN_LEGEND = ['居民-短贷', '居民-中长贷', '企业-短贷', '企业-中长贷', '企业-票据融资']
- export function loanStructureOption(d) {
- const cats = (d.categories || []).map((x) => String(x).slice(2, 7))
- const series = [
- { key: 'hhShort', name: '居民-短贷' },
- { key: 'hhMid', name: '居民-中长贷' },
- { key: 'corpShort', name: '企业-短贷' },
- { key: 'corpMid', name: '企业-中长贷' },
- { key: 'bill', name: '企业-票据融资' },
- ]
- return {
- tooltip: { ...tipOpt, trigger: 'axis', axisPointer: { type: 'shadow' } },
- legend: {
- data: LOAN_LEGEND,
- top: 6, type: 'scroll', textStyle: { color: C.mut, fontSize: 11 }, itemWidth: 14, itemHeight: 8,
- },
- grid: { top: 32, left: 56, right: 18, bottom: 28 },
- xAxis: { type: 'category', data: cats, ...axisStyle({ axisLabel: { color: C.mut, fontSize: 10, hideOverlap: true } }) },
- yAxis: { type: 'value', name: '亿元', ...axisStyle() },
- series: series.map((s, idx) => ({
- name: s.name, type: 'bar', stack: 'loan', data: d[s.key] || [],
- itemStyle: { color: LOAN_COLORS[idx], borderRadius: idx === 0 ? [3, 3, 0, 0] : 0 },
- barWidth: 18,
- })),
- }
- }
- // ============== 图4 近1年票据融资额 vs 10年国债(双 Y 轴) ==============
- export function billVsBond10Option(d) {
- const cats = (d.categories || []).map((x) => String(x).slice(2, 7))
- return {
- tooltip: { ...tipOpt, trigger: 'axis' },
- legend: {
- data: [
- { name: '近1年票据融资额', itemStyle: { color: '#7A4FCB' } },
- '10年国债到期收益率',
- ],
- top: 6, type: 'scroll', textStyle: { color: C.mut, fontSize: 11 }, itemWidth: 14, itemHeight: 8,
- },
- grid: { top: 32, left: 56, right: 56, bottom: 28 },
- xAxis: { type: 'category', data: cats, ...axisStyle({ axisLabel: { color: C.mut, fontSize: 10, hideOverlap: true } }) },
- yAxis: [
- {
- type: 'value', name: '亿元', position: 'left',
- ...axisStyle({ nameTextStyle: { color: C.mut, fontSize: 10 }, nameGap: 14 }),
- },
- {
- type: 'value', name: '%', position: 'right',
- min: 0, max: 5,
- ...axisStyle({ nameTextStyle: { color: C.mut, fontSize: 10 }, nameGap: 14 }),
- },
- ],
- series: [
- {
- name: '近1年票据融资额', type: 'bar',
- data: d.bill12m || [],
- barWidth: 12,
- itemStyle: {
- color: (p) => ({
- type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
- colorStops: [{ offset: 0, color: '#7A4FCB' }, { offset: 1, color: '#5B3DAE' }],
- }),
- borderRadius: [3, 3, 0, 0],
- },
- yAxisIndex: 0,
- },
- {
- name: '10年国债到期收益率', type: 'line', smooth: true,
- showSymbol: false, symbol: 'circle', symbolSize: 5,
- data: d.bond10 || [],
- yAxisIndex: 1,
- lineStyle: { color: C.warn, width: 2.4 },
- itemStyle: { color: C.warn },
- markLine: { symbol: ['none', 'none'], data: [{ yAxis: 0, lineStyle: { color: C.faint, type: 'dashed', width: 1 } }], label: { show: false } },
- },
- ],
- }
- }
- // ============== 图5 M1 同比 vs 10年国债(双 Y 轴) ==============
- export function m1VsBond10Option(d) {
- const cats = (d.categories || []).map((x) => String(x).slice(2, 7))
- return {
- tooltip: { ...tipOpt, trigger: 'axis' },
- legend: {
- data: ['M1 同比', '10年国债到期收益率'],
- top: 6, textStyle: { color: C.mut, fontSize: 11 }, itemWidth: 14, itemHeight: 8,
- },
- grid: { top: 32, left: 46, right: 46, bottom: 28 },
- xAxis: { type: 'category', data: cats, ...axisStyle({ axisLabel: { color: C.mut, fontSize: 10, hideOverlap: true } }) },
- yAxis: [
- {
- type: 'value', name: '%', position: 'left',
- ...axisStyle({ nameTextStyle: { color: C.mut, fontSize: 10 }, nameGap: 14 }),
- },
- {
- type: 'value', name: '%', position: 'right',
- min: 0, max: 5,
- ...axisStyle({ nameTextStyle: { color: C.mut, fontSize: 10 }, nameGap: 14 }),
- },
- ],
- series: [
- {
- name: 'M1 同比', type: 'line', smooth: true,
- showSymbol: false, symbol: 'circle', symbolSize: 5,
- data: d.m1Yoy || [],
- lineStyle: { color: C.brandD, width: 2.4 },
- itemStyle: { color: C.brandD },
- areaStyle: {
- type: 'linear', x: 0, y: 0, x2: 0, y2: 1,
- colorStops: [{ offset: 0, color: 'rgba(14,58,150,.10)' }, { offset: 1, color: 'rgba(14,58,150,0)' }],
- },
- yAxisIndex: 0,
- markLine: { symbol: ['none', 'none'], data: [{ yAxis: 0, lineStyle: { color: C.faint, type: 'dashed', width: 1 } }], label: { show: false } },
- },
- {
- name: '10年国债到期收益率', type: 'line', smooth: true,
- showSymbol: false, symbol: 'circle', symbolSize: 5,
- data: d.bond10 || [],
- yAxisIndex: 1,
- lineStyle: { color: C.warn, width: 2.4 },
- itemStyle: { color: C.warn },
- markLine: { symbol: ['none', 'none'], data: [{ yAxis: 0, lineStyle: { color: C.faint, type: 'dashed', width: 1 } }], label: { show: false } },
- },
- ],
- }
- }
- export function latestOf(series) {
- if (!series || !series.length) return null
- const last = series[series.length - 1]
- return { value: last[1], date: last[0] }
- }
|