Apex Chart - Help with scaling

Hi,
I’m working on an Apex chart to show the energy price, charge interval, and expensive price interval. So far, so good – but when I add my sensor that shows the energy I buy from the grid, things get a bit messy.

When I charge the car, the import series goes up (which is expected), but it affects the rest of the graph (data from my other series get so smal) I tried putting the import series on a separate y-axis, but then the “now” marker was pushed outside the visible area.

Is there a way to adjust my code so that the import line doesn’t affect the scaling of the rest of the graph? I just want to show how much energy I buy from the grid without letting it distort the overall chart.

type: custom:apexcharts-card
graph_span: 48h
span:
  start: day
  offset: +0H
header:
  title: Spotpris 48h ink moms
  show: false
  show_states: false
  colorize_states: true
hours_12: false
stacked: false
experimental:
  color_threshold: true
all_series_config:
  show:
    legend_value: false
    datalabels: false
    extremas: true
    in_brush: true
  float_precision: 3
  type: area
  invert: false
  fill_raw: last
now:
  show: true
  label: NU
  color: red
series:
  - entity: sensor.battery_charge_window_cheapest_1a
    name: Laddning 1a
    color: green
    type: area
    data_generator: |
      const data = [];
      const sensorData = entity.state.split(' - ');
      function parseLocalTime(str) {
        const parts = str.split(/[- :T]/).map(Number);
        const date = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
        return date.getTime();
      }
      const startTime = parseLocalTime(sensorData[0]);
      const endTime = parseLocalTime(sensorData[1]);
      data.push([startTime, 3]);
      data.push([startTime, 3]);
      data.push([endTime, 3]);
      data.push([endTime, 0]);
      return data;
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
      in_legend: false
  - entity: sensor.battery_charge_window_cheapest_1b
    name: Laddning 1b
    color: green
    type: area
    data_generator: |
      const data = [];
      const sensorData = entity.state.split(' - ');
      function parseLocalTime(str) {
        const parts = str.split(/[- :T]/).map(Number);
        const date = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
        return date.getTime();
      }
      const startTime = parseLocalTime(sensorData[0]);
      const endTime = parseLocalTime(sensorData[1]);
      data.push([startTime, 3]);
      data.push([startTime, 3]);
      data.push([endTime, 3]);
      data.push([endTime, 0]);
      return data;
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
      in_legend: false
  - entity: sensor.battery_charge_window_cheapest_2
    name: Laddning
    color: green
    type: area
    data_generator: |
      const data = [];
      const sensorData = entity.state.split(' - ');
      function parseLocalTime(str) {
        const parts = str.split(/[- :T]/).map(Number);
        const date = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
        return date.getTime();
      }
      const startTime = parseLocalTime(sensorData[0]);
      const endTime = parseLocalTime(sensorData[1]);
      data.push([startTime, 3]);
      data.push([startTime, 3]);
      data.push([endTime, 3]);
      data.push([endTime, 0]);
      return data;
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
      in_legend: true
  - entity: sensor.expensive_price_interval_1
    name: Dyrt
    color: pink
    type: area
    data_generator: |
      const data = [];
      const sensorData = entity.state.split(' - ');
      function parseLocalTime(str) {
        const parts = str.split(/[- :T]/).map(Number);
        const date = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
        return date.getTime();
      }
      const startTime = parseLocalTime(sensorData[0]);
      const endTime = parseLocalTime(sensorData[1]);
      data.push([startTime, 3]);
      data.push([startTime, 3]);
      data.push([endTime, 3]);
      data.push([endTime, 0]);
      return data;
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
  - entity: sensor.expensive_price_interval_2
    name: Dyrt 2
    color: pink
    type: area
    data_generator: |
      const data = [];
      const sensorData = entity.state.split(' - ');
      function parseLocalTime(str) {
        const parts = str.split(/[- :T]/).map(Number);
        const date = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
        return date.getTime();
      }
      const startTime = parseLocalTime(sensorData[0]);
      const endTime = parseLocalTime(sensorData[1]);
      data.push([startTime, 3]);
      data.push([startTime, 3]);
      data.push([endTime, 3]);
      data.push([endTime, 0]);
      return data;
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
      in_legend: false
  - entity: sensor.nordpool_kwh_se4_sek_1_10_0
    name: Idag
    opacity: 0.7
    color: black
    extend_to: false
    data_generator: >
      const data = entity.attributes.raw_today.map((start, index) => {
        return [new Date(start["start"]).getTime(), start["value"]];
      });

      const last = entity.attributes.raw_today.slice(-1)[0];

      const lastTime = new Date(last["start"]).getTime();

      data.push([lastTime + 3600000, last["value"]]); // Lägg till 00:00 nästa
      dag

      return data;
    color_threshold:
      - value: -1
        color: 1E90FF
      - value: 0.5
        color: "008000"
      - value: 1
        color: DAA520
      - value: 2
        color: FF0000
  - entity: sensor.nordpool_kwh_se4_sek_1_10_0
    name: Imorgon
    opacity: 0.7
    color: grey
    data_generator: >
      return entity.attributes.raw_tomorrow.map((start, index) => { return [new
      Date(start["start"]).getTime(),
      entity.attributes.raw_tomorrow[index]["value"]]; });
    color_threshold:
      - value: -1
        color: 1E90FF
      - value: 0.5
        color: "008000"
      - value: 1
        color: DAA520
      - value: 2
        color: FF0000
  - entity: sensor.solar_forecast_west
    data_generator: |
      return entity.attributes.west.watts.map((entry) => {
        return [new Date(entry.date), entry.values / 1000]; // Konvertera till kWh
      });
    name: Solel
    type: area
    color: orange
    opacity: 0.2
    stroke_width: 3
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
      in_legend: false
  - entity: sensor.el_import_timme
    name: Import
    color: "#154c79"
    color_threshold:
      - value: -1
        color: 154c79
      - value: 0.5
        color: 154c79
      - value: 1
        color: 154c79
      - value: 2
        color: 154c79
    float_precision: 1
    show:
      extremas: false
    type: line
    stroke_width: 3
    extend_to: false
    group_by:
      func: delta
      duration: 1h
apex_config:
  chart:
    height: 280px
    animations:
      enabled: true
      easing: easeinout
      speed: 800
      animateGradually:
        enabled: true
        delay: 150
  zoom:
    enabled: true
    type: x
    autoScaleYaxis: true
    zoomedArea:
      fill:
        color: "#90CAF9"
        opacity: 0.4
      stroke:
        color: "#0D47A1"
        opacity: 0.4
        width: 1
  legend:
    show: true
    floating: false
    offsetY: 10
  yaxis:
    opposite: false
    reversed: false
    logarithmic: false
    decimalsInFloat: 1
    labels:
      show: true
    tooltip:
      enabled: false
    crosshairs:
      show: true
    min: -0.1
    title:
      text: SEK/kWh
  xaxis:
    labels:
      show: true
      rotate: -40
      rotateAlways: true
    tooltip:
      enabled: false
    logarithmic: true
  stroke:
    show: true
    colors: undefined
  plotOptions:
    candlestick:
      colors:
        upward: "#00B746"
        downward: "#EF403C"
      wick:
        useFillColor: true
  markers:
    size: 1
  grid:
    show: true
    strokeDashArray: 1
    position: front
    xaxis:
      lines:
        show: true

You could use a different y-axis for import… have a look in the docs or try searching this long post, which is btw the best place to post things as it is on the notif list of multiple people

ApexCharts card - A highly customizable graph card - Share your Projects! / Dashboards & Frontend - Home Assistant Community

I tried that but when it got messy and now was outside the chart.

Thaks for that post tip. I will post it there instead.

Did u solv it? Can u share the code?

type: custom:apexcharts-card
update_interval: 5 min
graph_span: 48h
cache: false
span:
  start: day
  offset: +0H
header:
  title: Spotpris 48h ink moms
  show: false
  show_states: false
  colorize_states: true
hours_12: false
stacked: false
experimental:
  color_threshold: true
yaxis:
  - id: spotpris
    opposite: false
    show: true
    decimals: 1
    min: 0
    apex_config:
      title:
        text: Elpris (SEK/kWh)
  - id: solar_power
    opposite: true
    show: false
  - id: charge/expensive
    opposite: true
    show: false
apex_config:
  chart:
    height: 255
    animations:
      enabled: true
      easing: easeinout
      speed: 800
      animateGradually:
        enabled: true
        delay: 150
  legend:
    show: true
    floating: false
    offsetY: 5
    position: bottom
    fontSize: 10px
  tooltip:
    enabled: false
  xaxis:
    labels:
      show: true
      rotate: 0
      rotateAlways: true
      logarithmic: false
      datetimeUTC: false
  stroke:
    width: 1
  plotOptions:
    candlestick:
      colors:
        upward: "#00B746"
        downward: "#EF403C"
      wick:
        useFillColor: true
all_series_config:
  show:
    legend_value: false
    datalabels: false
    in_brush: false
  float_precision: 3
  invert: false
  fill_raw: last
now:
  show: true
  label: NU
  color: red
series:
  - entity: sensor.sem_solar_forecast
    yaxis_id: solar_power
    data_generator: |
      return entity.attributes.sem.watts.map((entry) => {
        return [new Date(entry.date), entry.values / 1000]; // Konvertera till kWh
      });
    name: Solel
    type: area
    color: orange
    opacity: 0.7
    stroke_width: 3
    color_threshold:
      - value: 0
        color: "#fff9c4"
      - value: 5
        color: "#ffeb3b"
      - value: 15
        color: "#fbc02d"
  - entity: sensor.sem_nordpool_active
    yaxis_id: spotpris
    type: area
    name: Idag
    opacity: 0.7
    color: grey
    extend_to: false
    data_generator: |
      const data = entity.attributes.raw_today.map((start, index) => {
        return [new Date(start["start"]).getTime(), start["value"]];
      });
      const last = entity.attributes.raw_today.slice(-1)[0];
      const lastTime = new Date(last["start"]).getTime();
      data.push([lastTime + 3600000, last["value"]]); // 
      return data;
    color_threshold:
      - value: -1
        color: 1E90FF
      - value: 0.5
        color: "008000"
      - value: 1
        color: DAA520
      - value: 2
        color: FF0000
    show:
      legend_value: false
      datalabels: false
      extremas: true
      in_brush: false
      in_legend: false
  - entity: sensor.sem_nordpool_active
    yaxis_id: spotpris
    name: Imorgon
    type: area
    opacity: 0.7
    color: grey
    data_generator: >
      const data = entity.attributes.raw_tomorrow.map((start, index) => {
        return [new Date(start["start"]).getTime(), start["value"]];
      });

      const last = entity.attributes.raw_tomorrow.slice(-1)[0]; const lastTime =
      new Date(last["start"]).getTime();

      data.push([lastTime + 3600000, last["value"]]);

      return data;
    color_threshold:
      - value: -1
        color: 1E90FF
      - value: 0.5
        color: "008000"
      - value: 1
        color: DAA520
      - value: 2
        color: FF0000
    show:
      legend_value: false
      datalabels: false
      extremas: true
      in_brush: false
      in_legend: false
  - entity: sensor.sem_battery_charge_window_cheapest_1a
    yaxis_id: charge/expensive
    name: Laddningsfönster 1
    opacity: 0.7
    color: "#00406c"
    type: area
    data_generator: |
      const data = [];
      const sensorData = entity.state.split(' - ');
      function parseLocalTime(str) {
        const parts = str.split(/[- :T]/).map(Number);
        const date = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
        return date.getTime();
      }
      const startTime = parseLocalTime(sensorData[0]);
      const endTime = parseLocalTime(sensorData[1]);
      data.push([startTime, 3]);
      data.push([startTime, 3]);
      data.push([endTime, 3]);
      data.push([endTime, 0]);
      return data;
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
      in_legend: true
  - entity: sensor.sem_battery_charge_window_cheapest_2
    yaxis_id: charge/expensive
    name: Laddningsfönster 2
    opacity: 0.7
    color: "#00406c"
    type: area
    data_generator: |
      const data = [];
      const sensorData = entity.state.split(' - ');
      function parseLocalTime(str) {
        const parts = str.split(/[- :T]/).map(Number);
        const date = new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
        return date.getTime();
      }
      const startTime = parseLocalTime(sensorData[0]);
      const endTime = parseLocalTime(sensorData[1]);
      data.push([startTime, 3]);
      data.push([startTime, 3]);
      data.push([endTime, 3]);
      data.push([endTime, 0]);
      return data;
    show:
      legend_value: false
      datalabels: false
      extremas: false
      in_brush: false
      in_legend: true