elden1337 / hass-peaqnext

Utility sensors to help find the next best usage of your appliances
Other
7 stars 0 forks source link

Perhaps not wrong, but… #27

Closed nord- closed 1 year ago

nord- commented 1 year ago

This is perhaps not wrong, but it's not what I expected… I have an hourly sensor, set at 60 minutes and flat consumption. It suggests the start time to 21:00, but 22, 23, 00, 01, 02, 03, 04 and 05 are all better/cheaper start times.

My expectations are that the sensor should choose the cheapest start time in the next 12 hours, recalculated every hour. And the first if there are several that are cheapest.

image

From the data in my current example (I have removed all times >12h) you can see that 23:00 should be the start time, or am I missing some other parameter that suggests that 21:00 is better than all other up until 6 o'clock?

elden1337 commented 1 year ago

It's the comparer that does this. For convenience sake it's rounding to one decimal causing 0.24 to be same as 0.18 so that one does not have to wait longer than necessary when the diff is very small.

nord- commented 1 year ago

Thank you for the clarification! Then I understand why this is happening! 🙃 Is it that slow to sort/filter the prices with two decimals?

elden1337 commented 1 year ago

no it's equally fast, but it's imo an uneeded opt that would make experience worse for very little financial gain (you'd have to wait longer). if you would be using öre or € or cents the comparer is more precise since 0.05 euro is much more per kwh than kr ofc.

nord- commented 1 year ago

It rounds to one decimal, right? What rounding strategy is used? Because this is strange: image I would say that 13:00 is the first 0,2 kr, but Peaqnext says 20:00 (0,15 kr) which I round to also 0,2 ("away from zero"-strategy)…

At this time it's more than 12 hours to 21 and 22, so those are disqualified... 🙂

elden1337 commented 1 year ago

the round()-func in python builtins rounds 0.15 to 0.1 when using 1 dec. this is why. stupid i know, i just found out myself.

nord- commented 1 year ago

👍

Did a little experiment in Python (my first lines of code in Python! :yay:)

from decimal import Decimal, ROUND_HALF_UP
import math

def round_away_from_zero(x, dec):
    """Round a number x away from 0."""
    return float(Decimal(x*math.pow(10,dec)).quantize(Decimal(0), rounding=ROUND_HALF_UP))/math.pow(10,dec)

print('-1.5:', round(-1.5), round_away_from_zero(-1.5,0), sep='\t')
print('-0.5:', round(-0.5), round_away_from_zero(-0.5,0), sep='\t')
print('0.5:', round(0.5), round_away_from_zero(0.5,0), sep='\t')
print('1.5:', round(1.5), round_away_from_zero(1.5,0), sep='\t')
print('2.5:', round(2.5), round_away_from_zero(2.5,0), sep='\t')
print('0.15:', round(0.15, 1), round_away_from_zero(0.15,1), sep='\t')
print(round_away_from_zero(2.21,1))
print(round_away_from_zero(2.5,1))
print(round_away_from_zero(2.55,1))
-1.5:   -2  -2.0
-0.5:    0  -1.0
 0.5:    0   1.0
 1.5:    2   2.0
 2.5:    2   3.0
 0.15:   0.1     0.2
 2.2
 2.5
 2.6

edit: the first always rounded up (ceiling) which was not intended.

elden1337 commented 1 year ago

Yes, also stumbled on this when i googled this very weird standard. Baffles me why theyve decided to do it this way.

elden1337 commented 1 year ago

I could cheat this by just adding a fraction to the val before rounding it. Ugly but i might do it.

nord- commented 1 year ago

Why not implement a rounding function that rounds correctly?

elden1337 commented 1 year ago

Because of prio mostly. But if you wish you may do it. Otherwise when time is right.

nord- commented 1 year ago

I might take a look at it this weekend, if I get bored… 😅

elden1337 commented 1 year ago

I read up some more on it. It's apparently called bankers rounding and is made to take the bias out of rounding in finance.

elden1337 commented 1 year ago

hour_model.py is where you want to inject a change. But if you would introduce such a method, feel free to put it elsewhere. Here are all roundings in the repo:

https://github.com/search?q=repo%3Aelden1337%2Fhass-peaqnext%20round(&type=code