Browse Source

Merge branch 'aiEmotion' of http://39.101.133.168:8807/hongxilin/AIxiaocaishen into aiEmotion

aiEmotion
ducaixia 4 weeks ago
parent
commit
d27e632f40
  1. 469
      src/views/components/emoEnergyConverter.vue
  2. 11
      src/views/components/emotionalBottomRadar.vue

469
src/views/components/emoEnergyConverter.vue

@ -3,102 +3,424 @@
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, toRef } from 'vue';
import * as echarts from 'echarts';
import { ref, onMounted, onBeforeUnmount, toRef, reactive } from "vue";
import * as echarts from "echarts";
defineExpose({initQXNLZHEcharts})
defineExpose({ initQXNLZHEcharts });
const qxnlzhqEchartsRef = ref(null);
let qxnlzhqEchartsRef = ref(null);
let qxnlzhqEchartsInstance = null;
const data = ref({
echartsData:{}
})
let {
echartsData
} = toRef(data.value)
let regions = reactive([]);
//
function getNameTop(min, max, regionMiidle) {
//
const chartHeight = qxnlzhqEchartsInstance.getHeight();
// 60: x
return (max - Number(regionMiidle)) / (max - min) * (chartHeight - 60)
}
//
function getNumberTop(min, max, regionMax) {
//
const chartHeight = qxnlzhqEchartsInstance.getHeight();
// 60: x
return (max - Number(regionMax)) / (max - min) * (chartHeight - 60)
}
//
const generateGraphics = (min, max) => {
return regions.flatMap((region) => {
const middleY = (Number(region.min) + Number(region.max)) / 2;
return [
//
{
type: "text",
left: '17', // y
top: getNameTop(min, max, middleY),
style: {
text: region.name,
fill: region.fontColor,
fontSize: 14,
fontWeight: "bold",
},
z: 3,
},
// y
{
type: "text",
left: '25',
top: getNumberTop(min, max, region.max),
// top: 100,
style: {
text: region.max.toString(),
fill: region.NumberColor,
fontSize: 12,
},
z: 3,
},
];
});
};
function initQXNLZHEcharts(kline, qxnlzhqData) {
console.log('kline', kline)
console.log('qxnlzhqData', qxnlzhqData)
let mixData = []
kline.forEach(element => {
let date = element[0]
let value = [element[1],element[2],element[3],element[4]]
//
// qxnlzhqData.topxh = ["2025/04/04", "2025/04/15"]
// qxnlzhqData.lowxh = ["2025/04/08", "2025/04/18"]
// qxnlzhqData.qixh = ["2025/04/10", "2025/04/21"]
if (qxnlzhqEchartsInstance) {
qxnlzhqEchartsInstance.dispose();
}
//
let mixData = [];
kline.forEach((element) => {
let date = element[0];
let value = [element[1], element[2], element[3], element[4]];
mixData.push({
date,
value
})
value,
});
});
//
// ddzc ------ zcht ------ htqs ------ qstp ------
// tpjs ------ jsyl ------- ylgg -------
regions = [
{
min: qxnlzhqData.dd,
max: qxnlzhqData.zc,
name: "【情绪冰点区】",
color: "#e7a5d6",
fontColor: '#000',
NumberColor: 'blue',
},
{
min: qxnlzhqData.zc,
max: qxnlzhqData.ht,
name: "【认知潜伏区】",
color: "#f36587",
fontColor: '#000',
NumberColor: 'blue',
},
{
min: qxnlzhqData.ht,
max: qxnlzhqData.qs,
name: "【多空消化区】",
color: "#e99883",
fontColor: '#000',
NumberColor: 'blue',
},
{
min: qxnlzhqData.qs,
max: qxnlzhqData.tp,
name: "【共识加速区】",
color: "#f0db84",
fontColor: '#000',
NumberColor: 'red',
},
{
min: qxnlzhqData.tp,
max: qxnlzhqData.js,
name: "【情绪临界区】",
color: "#dbeee3",
fontColor: 'red',
NumberColor: 'red',
},
];
// gg yl-1
if (Number(qxnlzhqData.yl) != -1) {
regions.push(
{
min: qxnlzhqData.js,
max: qxnlzhqData.yl,
name: "【杠杆失衡区】",
color: "#9ac2d8",
fontColor: 'red',
NumberColor: 'red',
},
)
}
if (Number(qxnlzhqData.gg) != -1) {
regions.push(
{
min: qxnlzhqData.yl,
max: qxnlzhqData.gg,
name: "【情绪熔断区】",
color: "#bce283",
fontColor: 'red',
NumberColor: 'red',
},
)
}
//
const stopProfitPrice = Number(qxnlzhqData.cc) * 1.05; //
const stopLossPrice = Number(qxnlzhqData.cc) * 0.97; //
//
const startIndex = Math.max(0, mixData.length - 17);
//
const takeProfitData = new Array(mixData.length).fill(null);
const stopLossData = new Array(mixData.length).fill(null);
//
for (var i = startIndex; i < mixData.length; i++) {
takeProfitData[i] = stopProfitPrice;
stopLossData[i] = stopLossPrice;
}
// topxhlowxhqixh k线
//
const middleRangeData = [];
const middleRangeData1 = [];
const markPointData = [];
mixData.forEach((item, index) => {
const [open, close, low, high] = item.value;
const rangeHeight = high - low;
// const middleThirdStart = low + rangeHeight * (1/3);
// const middleThirdEnd = low + rangeHeight * (2/3);
let color = null;
if (qxnlzhqData.topxh.includes(item.date)) {
color = '#000000'; //
} else if (qxnlzhqData.lowxh.includes(item.date)) {
color = '#1E90FF'; //
}
//
if (color) {
middleRangeData.push({
value: [index, close > open ? (close - open) : (open - close)], //
itemStyle: {
normal: {
color: color
}
},
});
middleRangeData1.push({
value: [index, close > open ? open : close], //
itemStyle: {
normal: {
color: 'transparent'
}
},
});
} else {
middleRangeData.push(null);
middleRangeData1.push(null);
}
//
if (qxnlzhqData.qixh.includes(item.date)) {
markPointData.push({
name: '起',
coord: [index, (open + close) / 2],
itemStyle: {
normal: {
color: 'rgba(0,0,0,0)' //
}
},
label: {
normal:{
show: true,
position: 'inside',
formatter: '起',
textStyle: {
color: '#FF0000',
fontSize: 10,
// fontWeight: 'bold'
}
}
}
});
}
});
console.log('mixData---',mixData)
//
qxnlzhqEchartsInstance = echarts.init(qxnlzhqEchartsRef.value);
let option;
//
const option = {
option = {
xAxis: {
type: 'category',
data: mixData.map(item => item.date),
type: "category",
data: mixData.map((item) => item.date),
axisLabel: {
rotate: 45, // 45
}
},
},
yAxis: {
scale: true,
splitLine: {
show: false
show: false,
},
axisLabel: {
// formatter: '{value}'
}
axisLabel: { //
show: false //
},
axisTick: { // 线
show: false // 线
},
min:
qxnlzhqData.dd < stopLossPrice * 0.98
? Math.floor(qxnlzhqData.dd)
: Math.floor(stopLossPrice * 0.98),
max:
qxnlzhqData.yl > stopProfitPrice * 1.02
? Math.ceil(qxnlzhqData.yl)
: Math.ceil(stopProfitPrice * 1.02),
},
series: [{
type: 'candlestick',
data: mixData.map(item => item.value),
itemStyle: {
// // 线 >
// color: '#ff0783', // 线
// borderColor: '#ff0783',
// color0: 'transparent', // 线
// borderColor0: '#ff0783',
// // 线 <
// color: '#008080', // 线绿
// borderColor: '#008080',
// color0: '#008080', // 线
// borderColor0: '#008080',
//
// emphasis: {
// color: '#ff6666', // 线
// borderColor: '#ff6666',
// color0: 'rgba(255,102,102,0.3)', // 线
// borderColor0: '#ff6666',
// color: '#66cc99', // 线
// borderColor: '#66cc99',
// color0: '#66cc99',
// borderColor0: '#66cc99'
// }
normal: {
// 线 >
color: '#ef232a', // 线
color0: '#14b143', // 线
borderColor: '#ef232a', // 线
borderColor0: '#14b143', // 线绿
// opacity
opacity: function(params) {
// > 线
return params.data[2] > params.data[1] ? 0 : 1;
//
graphic: generateGraphics(qxnlzhqData.dd < stopLossPrice * 0.98
? Math.floor(qxnlzhqData.dd)
: Math.floor(stopLossPrice * 0.98),qxnlzhqData.yl > stopProfitPrice * 1.02
? Math.ceil(qxnlzhqData.yl)
: Math.ceil(stopProfitPrice * 1.02)),
series: [
{
type: "candlestick",
data: mixData.map((item) => item.value),
z: 1,
markPoint: {
symbol: 'circle',
symbolSize: 10,
data: markPointData,
z: 5 //
},
itemStyle: {
normal: {
// 线 >
color: 'transparent', // 线
color0: '#008080', // 线
borderColor: '#ff0783', // 线
borderColor0: '#008080', // 线绿
}
},
//
markArea: {
silent: true,
data: regions.map((region) => [
{
yAxis: region.min,
itemStyle: { normal: { color: region.color } },
},
{ yAxis: region.max },
]),
},
},
{
name: '中间区域',
type: 'bar',
stack: 'total',
data: middleRangeData1,
barWidth: '10%',
barCategoryGap: '45%',
itemStyle: {
normal: {
color: 'rgba(0,0,0,0)' //
}
},
z:2
},
//
{
name: '中间区域',
type: 'bar',
stack: 'total',
data: middleRangeData,
barWidth: '10%',
barCategoryGap: '45%',
itemStyle: {
normal: {
color: 'rgba(0,0,0,0)' //
}
},
z:2
},
{
name: '止盈线',
type: 'line',
data: takeProfitData,
symbol: 'none',
lineStyle: {
normal: {
color: '#ff80ff', //
width: 2,
type: 'solid'
}
},
markPoint: {
symbol: 'circle',
symbolSize: 1,
data: [
{
coord: [mixData.map((item) => item.value).length - 1, stopProfitPrice],
itemStyle: {
color: '#ff80ff'
},
label: {
normal: {
show: true,
position: 'bottom',
formatter: `{text|止盈: ${stopProfitPrice}}`,
rich: {
text: {
color: '#820a06',
fontSize: 14,
fontWeight: 'bold'
}
}
}
}
}
]
}
}
}],
},
{
name: '止损线',
type: 'line',
data: stopLossData,
symbol: 'none',
lineStyle: {
normal: {
color: '#080bfd', //
width: 2,
type: 'solid'
}
},
markPoint: {
symbol: 'circle',
symbolSize: 1,
data: [
{
coord: [mixData.map((item) => item.value).length - 1, stopLossPrice],
itemStyle: {
color: '#080bfd'
},
label: {
normal: {
show: true,
position: 'bottom',
formatter: `{text|止损: ${stopLossPrice}}`,
rich: {
text: {
color: '#080bfd',
fontSize: 14,
fontWeight: 'bold'
}
}
}
}
}
]
}
},
],
grid: {
left: '3%',
right: '4%',
bottom: '4%', // dataZoom
containLabel: true
}
left: "0",
right: "10",
top: '10',
bottom: "0",
containLabel: true,
},
};
//
qxnlzhqEchartsInstance.setOption(option);
@ -112,9 +434,8 @@ onBeforeUnmount(() => {
});
</script>
<style scoped>
#qxnlzhqEcharts{
#qxnlzhqEcharts {
width: 100%;
height: 600px;
border: 1px solid red;
}
</style>

11
src/views/components/emotionalBottomRadar.vue

@ -6,10 +6,10 @@
import { ref } from 'vue'
import * as echarts from 'echarts'
const bottomRadarRef = ref(null)
let bottomRadarChart = null
function initEmotionalBottomRadar(KlineData, barAndLineData) {
console.log('KlineData, barAndLineData---', KlineData, barAndLineData)
let bottomRadarChartDom = document.getElementById('bottomRadarChart')
let bottomRadarChart = echarts.init(bottomRadarChartDom)
bottomRadarChart = echarts.init(bottomRadarChartDom)
// -x
let dateArray = KlineData.map(subArray => subArray[0])
@ -543,6 +543,13 @@ function initEmotionalBottomRadar(KlineData, barAndLineData) {
defineExpose({
initEmotionalBottomRadar
})
onBeforeUnmount(() => {
//
if (bottomRadarChart) {
bottomRadarChart.dispose()
}
})
</script>
<style>

Loading…
Cancel
Save