I don't like how all characters follow the same pattern, visiting shops strictly if self.flag("day_since_shopping") > 5. It probably could be trait based.
I try to randomize the days as much as possible so they are not shopping on the same day. Shopping should also not activate when chars are working. You can tweak and twist that as you want, we'll may even introduce shopping events in the future

Is there any difference in terms of speed between if ((a>b) and (c>d)) and if all(a>b, c>d)?
if a>b and c>d:
# Do something...
is faster for sure. I actually think that any()/all() are only faster when you have a prepared container for them to work with, otherwise they would have to build generators/containers before execution and that will always take some time. The reason I use sometimes use them is better readability and in places where we don't give a sh!t about speed (stuff that just runs during gameplay in labels is close to impossible to overload with logic on modern machines and old machines

). Anything during the Next Day is the most brutal... In future we can sneak some calculations while the player is just playing the game (move them from ND) but that kind of optimization is in distant future.
===
But this will not matter a lot in this case. Best improvements are when you can fix plainly bad coding and/or move stuff to modules that are executed in C which is always much faster.