// 融资需求与货币供给 — 图表配置 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] } }