I have made a simple scenario in the code below. It produces the following dataframe
My issue arises in snapshot 2, where the marginal price at node_1 is 140. Because the load is 150 MW at this snapshot node_1 needs to import 100 MW. Because of the ramping limitation of 60 MW up and down, the import is 40 MW for node_1 in the neighboring snapshots. This further makes node_1 reduce its wind production because there is too little consumption in those neighboring snapshots.
It makes sense that the marginal price on node_1 is 5 in the neighboring snapshots, since the wind production is decreased. However the power imported is produced by a gas technology, and hence costs 50 to produce those MW.
The price in snapshot 2 on node_1 being 140 is a bit unclear, can anyone please help me understand how 140 is calculated, thanks!
I would expect the price to be 50 as that is the price of the gas.
However, since the gas technologies need payment for the neighboring snapshots (1 and 3), then I also understand that the price should be increased for snapshot 2. But I would think that the calculations should be something like:
compensation for the imported power at snapshot 1 and 3:
compensation_1_3 = (40 + 40) * (50 - 5) = 3600
While the imported power at 2 is:
earnings_2 = 100*50 = 5000
So, in order for the producers on node_2 to be properly compensated, the price for snapshot 2 should be:
price_2 = (earnings_2 + compensation_1_3)/import_2 = 8600/100 = 86
But as I can see from the optimization, this is not the case.
import pypsa
import pandas as pd
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
network = pypsa.Network()
# snapshots
network.set_snapshots(range(4))
# define nodes
network.add(
class_name="Bus",
name="node_1"
)
network.add(
class_name="Bus",
name="node_2"
)
# add load
network.add(
class_name="Load",
name="node_1 load",
bus="node_1",
p_set=pd.Series(data=[49, 52, 150, 49])
)
network.add(
class_name="Load",
name="node_2 load",
bus="node_2",
p_set=pd.Series(data=[49, 49, 49, 49])
)
# add generators
network.add(
class_name="Generator",
name="node_1 wind",
bus="node_1",
p_min_pu=0,
p_nom=100,
marginal_cost=5,
p_max_pu=pd.Series(data=[0.5, 0.5, 0.5, 0.5])
)
network.add(
class_name="Generator",
name="node_2 wind",
bus="node_2",
p_min_pu=0,
p_nom=100,
marginal_cost=5,
p_max_pu=pd.Series(data=[0.5, 0.5, 0.5, 0.5])
)
network.add(
class_name="Generator",
name="node_2 gas",
bus="node_2",
p_min_pu=0,
p_nom=100,
marginal_cost=50,
)
# link
network.add(
class_name="Link",
name="node_1 -> node_2 link",
bus0="node_1",
bus1="node_2",
ramp_limit_up=60/200,
ramp_limit_down=60/200,
p_nom=200,
p_min_pu=-1
)
# optimize network
status = network.optimize()
# get data
loads = network.loads_t.p
production = network.generators_t.p
links = network.links_t.p0
prices = network.buses_t.marginal_price
# join data
data = loads.join(production)
data = data.join(links)
data = data.join(prices)