def lambda_taker_price(): Horizon_T = 48 day = 2 H, h, Mn, b, P_max, P_min, d = get_basics(Horizon_T, day) n = d.shape[0] # number of nodes """ Find lambdas for the day (they will be deemed exogenous) """ lambdas = np.zeros((n, Horizon_T)) for j in range(Horizon_T): """ Here is a new optimization framework which is rigoursely the same as devised in the algorithm, WARNING this is just for time period j. We input the c and q, the price and quantity offered by the battery. Here 0,0 because we want the LMPs without the battery """ c = 0 q = 0 model = economic_dispatch.run_ED_1period(d[:, j], b[:, j], P_max[:, j], P_min[:, j], c, q, H, h, Mn) for k in range(n): lambdas[k, j] = model.dual[model.injection_definition[ k]] # here we store the dual variables of the injection definition constraint lambda_base = lambdas[10] z_cap = 10 lambdas_cap = [] z_caps = [5, 10, 15] + list(np.linspace(1, 500, 25)) for z_cap in z_caps: i_Battery = 10 model = price_taking_algorithm.run_program(lambdas, i_battery=i_Battery, cost_of_battery=0, max_capacity=z_cap) planning = [pyo.value(model.u[t]) for t in range(Horizon_T) ] # planning of push and pull from the network expected_profits = sum([ planning[i] * lambdas[1, i] for i in range(Horizon_T) ]) # expected profits (lambda cross u with lambdas as exogenous) n_lambdas = np.zeros((n, Horizon_T)) # new prices ! for j in range(Horizon_T): """ Here we sell and buy at 0 (i.e we self-schedule_) the quantity devised in the optimization algorithm """ model = economic_dispatch.run_ED_1period(d[:, j], b[:, j], P_max[:, j], P_min[:, j], 0, planning[j], H, h, Mn, i_battery=i_Battery) for k in range(n): n_lambdas[k, j] = model.dual[model.injection_definition[k]] actual_profits = sum( [planning[i] * n_lambdas[1, i] for i in range(Horizon_T)]) lambdas_pt = n_lambdas[i_Battery] lambdas_cap.append(lambdas_pt) lambdas_cap_pm = [] z_caps_pm = np.linspace(1, 500, 10) for z_cap in z_caps_pm: i_Battery = 10 model = price_making_algorithm.run_program(d, b, P_max, P_min, H, h, Mn, i_battery=i_Battery, max_capacity=z_cap, cost_of_battery=0) lambda_ = [[pyo.value(model.lambda_[i, t]) for t in range(Horizon_T)] for i in range(d.shape[0])] lambdas_pt = lambda_[i_Battery] lambdas_cap_pm.append(lambdas_pt) z_caps = [z_caps[3]] + z_caps[:3] + z_caps[4:] norm = [] norm_pm = [] for n_l in lambdas_cap: norm.append(np.sqrt(sum(np.array(lambda_base - n_l)**2))) for n_l in lambdas_cap_pm: norm_pm.append(np.sqrt(sum(np.array(lambda_base - n_l)**2))) norm = [norm[3]] + norm[:3] + norm[4:] import matplotlib.pyplot as plt plt.figure(figsize=(10, 8)) plt.plot( z_caps, norm, marker="x", linestyle="dashed", label=r'price taker : $||\lambda^{bl}_{10} - \lambda^{pt}_{10}||_2$') plt.plot( z_caps_pm, norm_pm, marker="o", label=r'price maker : $||\lambda^{bl}_{10} - \lambda^{pm}_{10}||_2$') plt.title("Price taker vs maker strategy influence on LMP at node 10") plt.xlabel(r"z^{cap}") plt.axhline(y=0, label="no difference in prices", color="black", linestyle="dotted") plt.ylabel("Norm 2 Difference between lmp without and with battery") plt.legend() plt.show()
def comparing_strategy(): Horizon_T, day = 48, 2 H, h, Mn, b, P_max, P_min, d = get_basics(Horizon_T, day) n = d.shape[0] # number of nodes y = 4.5 # amortize in 10 years cost_of_battery = 200 * 1000 / (y * 365) print("Launching model...") model_pm = price_making_algorithm.run_program(d, b, P_max, P_min, H, h, Mn, i_battery=10, max_capacity=17, cost_of_battery=0) model_pm.z_cap.pprint() u = [pyo.value(model_pm.u[t]) for t in range(Horizon_T)] # or do that for array variable lambda_ = [[pyo.value(model_pm.lambda_[i, t]) for t in range(Horizon_T)] for i in range(d.shape[0])] df = pd.DataFrame(data=[u, lambda_[10]]).T df["benefits"] = df[0] * df[1] df["cumulated profits"] = df["benefits"].cumsum() df["z"] = [pyo.value(model_pm.z[t]) for t in range(Horizon_T)] # test = pd.DataFrame(data=[lambdas[10], lambda_[10]]) model_pt = price_taking_algorithm.run_program(lambdas, i_battery=10, cost_of_battery=0, max_capacity=17) df_pt = pd.DataFrame() # df_pt["u"] = planning planning = [pyo.value(model_pt.u[t]) for t in range(Horizon_T) ] # planning of push and pull from the network expected_profits = sum([ planning[i] * lambdas[10, i] for i in range(Horizon_T) ]) # expected profits (lambda cross u with lambdas as exogenous) df_pt["u"] = planning df_pt["e_profits"] = [ planning[i] * lambdas[10, i] for i in range(Horizon_T) ] df_pt["cumulated e profits"] = df_pt["e_profits"].cumsum() n_lambdas = np.zeros((n, Horizon_T)) # new prices ! for j in range(Horizon_T): """ Here we sell and buy at 0 (i.e we self-schedule_) the quantity devised in the optimization algorithm """ model = economic_dispatch.run_ED_1period(d[:, j], b[:, j], P_max[:, j], P_min[:, j], 0, planning[j], H, h, Mn, i_battery=10) for k in range(n): n_lambdas[k, j] = model.dual[model.injection_definition[k]] # actual_profits = sum([planning[i] * n_lambdas[1, i] for i in range(Horizon_T)]) df_pt["a_profits"] = [ planning[i] * n_lambdas[10, i] for i in range(Horizon_T) ] df_pt["cumulated a profits"] = df_pt["a_profits"].cumsum() df_pt["z"] = [pyo.value(model_pt.z[t]) for t in range(Horizon_T)] plt.title("LMPs on node 10 taker vs maker") plt.plot(lambdas[10], label=r'$\lambda_{pm}$') plt.plot(n_lambdas[10], label=r'$\lambda_{pt}$') plt.legend() plt.ylabel('\$') plt.xlabel("Time [trading periods]") plt.grid("True") plt.show() fig, axs = plt.subplots(2, sharex=True, figsize=(12, 8), dpi=80, facecolor='w', edgecolor='k') plt.subplots_adjust(hspace=.0) fs = 20 axs[0].plot(df["cumulated profits"], color="black", marker="x", label="Cumulated profits - price maker") axs[0].plot(df_pt["cumulated e profits"], color="red", marker="o", label="Expected Cumulated profits - price taker") axs[0].plot(df_pt["cumulated a profits"], color="green", marker="*", label="Actuals Cumulated profits - price maker") axs[0].set_ylabel('\$', fontsize=fs) axs[0].set_ylim(bottom=0) axs[0].set_title( 'Cumulated profits and Cleared volumes, Maker vs Taker \n Baseline model, Sept. 2nd, 2019', fontsize=fs) axs[0].grid() axs[0].legend() axs[1].plot(df["z"], color="black", marker="x", linewidth=3, label="SOC - price maker") axs[1].plot(df_pt["z"], color="green", marker="x", linestyle="dashed", label="SOC - price taker") # for i, y_arr, label in zip(range(1, 20), Y[1:, :], Nodes[1:].tolist()): # if (label == 'MDN') | (label == 'HEN'): # axs[1].plot(y_arr, label=f'{i} : {label}', linewidth=5) # else: # axs[1].plot(y_arr, label=f'{i} : {label}') axs[1].legend() axs[1].set_ylabel('MWh', fontsize=fs) axs[1].set_xlabel('Time [h]', fontsize=fs) plt.xticks(range(0, 48, 2), range(24)) axs[1].set_xlim([0, 48]) axs[1].grid() plt.show()
def plot_norm_2(*args, z_caps = np.linspace(1, 100, 11)): d, b, P_max, P_min, H, h, Mn = args n, Horizon_T = d.shape lambdas = np.zeros((n, Horizon_T)) for j in range(Horizon_T): """ Here is a new optimization framework which is rigoursely the same as devised in the algorithm, WARNING this is just for time period j. We input the c and q, the price and quantity offered by the battery. Here 0,0 because we want the LMPs without the battery """ c = 0 q = 0 model = economic_dispatch.run_ED_1period(d[:, j], b[:, j], P_max[:, j], P_min[:, j], c, q, H, h, Mn) for k in range(n): lambdas[k, j] = model.dual[model.injection_definition[ k]] # here we store the dual variables of the injection definition constraint # g = np.array([pyo.value(model.g_t[i]) for i in range(b.shape[0])]) # cost_producer = np.inner(b[:,j], g) lambda_base = lambdas[10] lambdas_cap = [] # = [5, 10] + list(np.linspace(15, 200, 5)) for z_cap in z_caps: # print(z_cap) i_Battery = 10 model = price_taking_algorithm.run_program(lambdas, i_battery=i_Battery, cost_of_battery=0, max_capacity=z_cap, power_rate=2) planning = [pyo.value(model.u[t]) for t in range(Horizon_T)] # planning of push and pull from the network expected_profits = sum([planning[i] * lambdas[1, i] for i in range(Horizon_T)]) # expected profits (lambda cross u with lambdas as exogenous) n_lambdas = np.zeros((n, Horizon_T)) # new prices ! for j in range(Horizon_T): """ Here we sell and buy at 0 (i.e we self-schedule_) the quantity devised in the optimization algorithm """ model = economic_dispatch.run_ED_1period(d[:, j], b[:, j], P_max[:, j], P_min[:, j], 0, planning[j], H, h, Mn, i_battery=i_Battery) for k in range(n): n_lambdas[k, j] = model.dual[model.injection_definition[k]] actual_profits = sum([planning[i] * n_lambdas[1, i] for i in range(Horizon_T)]) lambdas_pt = n_lambdas[i_Battery] lambdas_cap.append(lambdas_pt) lambdas_cap_pm = [] # z_caps_pm = np.linspace(1, 500, 10) z_caps_pm = z_caps for z_cap in z_caps_pm: # print(z_cap) i_Battery = 10 model = price_making_algorithm.run_program(d, b, P_max, P_min, H, h, Mn, i_battery=i_Battery, max_capacity=z_cap, cost_of_battery=0, power_rate=2) lambda_ = [[pyo.value(model.lambda_[i, t]) for t in range(Horizon_T)] for i in range(d.shape[0])] lambdas_pt = lambda_[i_Battery] lambdas_cap_pm.append(lambdas_pt) # z_caps = [z_caps[3]] + z_caps[:3] + z_caps[4:] norm = [] norm_pm = [] for n_l in lambdas_cap: norm.append(np.mean(abs(np.array(lambda_base - n_l)))) for n_l in lambdas_cap_pm: norm_pm.append(np.mean(abs(np.array(lambda_base - n_l)))) # norm_pm.append(np.sqrt(sum(np.array(lambda_base - n_l) ** 2))) # norm = [norm[3]] + norm[:3] + norm[4:] plt.figure(figsize=(10, 6)) plt.plot(z_caps, norm, # linestyle="dashed", label=r'PT : $|\lambda^{BL}_{10} - \lambda^{PT}_{10}|$') plt.plot(z_caps_pm, norm_pm, label=r'PM : $|\lambda^{BL}_{10} - \lambda^{PM}_{10}|$') # plt.title("Price taker vs maker strategy influence on LMP at node 10 in function of installed capacity") plt.xlabel(r'$z_{cap}$ (in MWh)', fontsize=17) plt.ylabel(r'Average of absolute difference (in \$)', fontsize=17) # plt.axhline(y=0, label="no difference in prices", color="black", linestyle="dotted") # plt.ylabel("Norm 2 Difference between lmp without and with battery") plt.legend(fontsize=20) plt.yticks(fontsize=17) plt.xticks(fontsize=16) plt.show()
def plot_cum_prof(battery_index, lambdas, z_cap, *args): # battery_index = 12 # z_cap = 45 d, b, P_max, P_min, H, h, Mn = args n, Horizon_T = d.shape model_baseline = price_making_algorithm.run_program(d, b, P_max, P_min, H, h, Mn, i_battery=battery_index, max_capacity=0, cost_of_battery=0, power_rate=2) lambda_baseline = [[pyo.value(model_baseline.lambda_[i, t]) for t in range(Horizon_T)] for i in range(d.shape[0])] model_pm = price_making_algorithm.run_program(d, b, P_max, P_min, H, h, Mn, i_battery=battery_index, max_capacity=z_cap, cost_of_battery=0, power_rate=2) u = [pyo.value(model_pm.u[t]) for t in range(Horizon_T)] # or do that for array variable lambda_ = [[pyo.value(model_pm.lambda_[i, t]) for t in range(Horizon_T)] for i in range(d.shape[0])] df = pd.DataFrame(data=[u, lambda_[battery_index]]).T df["benefits"] = df[0] * df[1] df["cumulated profits"] = df["benefits"].cumsum() df["z"] = [pyo.value(model_pm.z[t]) for t in range(Horizon_T)] # test = pd.DataFrame(data=[lambdas[10], lambda_[10]]) model_pt = price_taking_algorithm.run_program(lambdas, i_battery=battery_index, cost_of_battery=0, max_capacity=z_cap, power_rate=2) df_pt = pd.DataFrame() # df_pt["u"] = planning planning = [pyo.value(model_pt.u[t]) for t in range(Horizon_T)] # planning of push and pull from the network expected_profits = sum([planning[i] * lambdas[battery_index, i] for i in range(Horizon_T)]) # expected profits (lambda cross u with lambdas as exogenous) df_pt["u"] = planning df_pt["e_profits"] = [planning[i] * lambdas[battery_index, i] for i in range(Horizon_T)] df_pt["cumulated e profits"] = df_pt["e_profits"].cumsum() n_lambdas = np.zeros((n, Horizon_T)) # new prices ! for j in range(Horizon_T): """ Here we sell and buy at 0 (i.e we self-schedule_) the quantity devised in the optimization algorithm """ model = economic_dispatch.run_ED_1period(d[:, j], b[:, j], P_max[:, j], P_min[:, j], 0, planning[j], H, h, Mn, i_battery=battery_index) for k in range(n): n_lambdas[k, j] = model.dual[model.injection_definition[k]] # actual_profits = sum([planning[i] * n_lambdas[1, i] for i in range(Horizon_T)]) df_pt["a_profits"] = [planning[i] * n_lambdas[battery_index, i] for i in range(Horizon_T)] df_pt["cumulated a profits"] = df_pt["a_profits"].cumsum() df_pt["z"] = [pyo.value(model_pt.z[t]) for t in range(Horizon_T)] # plt.title("LMPs on node 10 taker vs maker") # plt.plot(lambdas[10], label=r'$\lambda_{pm}$') # plt.plot(n_lambdas[10], label=r'$\lambda_{pt}$') # plt.legend(prop={'size': 17}) # plt.ylabel('\$') # plt.xlabel("Time [trading periods]") # plt.grid("True") # plt.show() lambda_gap_pt = n_lambdas[10] - lambda_baseline[10] lambda_gap_pm = lambdas[10] - lambda_baseline[10] fig, axs = plt.subplots(4, sharex=True, figsize=(12, 10), dpi=80, facecolor='w', edgecolor='k', gridspec_kw={"height_ratios": [2, 1, 1, 1]}) plt.subplots_adjust(hspace=.0) fs = 20 axs[0].plot(df["cumulated profits"], color="black", marker="x", label=r'Revenue PM') axs[0].plot(df_pt["cumulated e profits"], color="green", marker="o", label="Expected revenue PT") axs[0].plot(df_pt["cumulated a profits"], color="red", marker="*", label="Actual revenue PT") axs[0].set_ylabel('\$', fontsize=fs) # axs[0].set_title('Cumulated profits, SOC, Maker vs Taker', # fontsize=fs) # axs[0].grid() axs[0].legend(prop={'size': 17}) axs[1].bar(df_pt.index, df_pt["e_profits"] - df_pt["a_profits"], color="black", #marker="*", label="Expected-Actual PT") axs[1].set_ylabel('\$', fontsize=fs) # axs[0].grid() axs[1].legend(prop={'size': 17}, loc=2) axs[2].bar(df_pt.index, lambda_gap_pt, color="darkred", # marker="*", label=r"$\lambda_{PT} - \lambda_{BL}$") axs[2].set_ylabel('\$', fontsize=fs) # axs[0].grid() axs[2].legend(prop={'size': 17}, loc=2) axs[2].axhline(y=0, color="black", label=r"$\lambda_{PM} - \lambda_{BL}$") axs[3].bar(df.index-0.15, df[0], width=0.15, label=r'$u$ PM') #SOC - price maker") #color="black", marker="x", linewidth=3, label="SOC - price maker" axs[3].bar(df_pt.index+0.15, df_pt["u"], width=0.2, label=r'$u$ PT') #, color="green", marker="x", linestyle="dashed", label="SOC - price taker") axs[3].axhline(y=0, color="black") # for i, y_arr, label in zip(range(1, 20), Y[1:, :], Nodes[1:].tolist()): # if (label == 'MDN') | (label == 'HEN'): # axs[1].plot(y_arr, label=f'{i} : {label}', linewidth=5) # else: # axs[1].plot(y_arr, label=f'{i} : {label}') axs[3].legend(prop={'size': 17}, loc=2) axs[3].set_ylabel('MWh', fontsize=fs) axs[3].set_xlabel('Time [h]', fontsize=fs) plt.xticks(range(0, 48, 2), range(24)) axs[3].set_xlim([0, 48]) axs[0].axvspan(14, 17, alpha=0.1, color='black') axs[0].axvspan(20, 23, alpha=0.1, color='black') axs[0].axvspan(31, 41, alpha=0.1, color='black') axs[1].axvspan(14, 17, alpha=0.1, color='black') axs[1].axvspan(20, 23, alpha=0.1, color='black') axs[1].axvspan(31, 41, alpha=0.1, color='black') axs[2].axvspan(14, 17, alpha=0.1, color='black') axs[2].axvspan(20, 23, alpha=0.1, color='black') axs[2].axvspan(31, 41, alpha=0.1, color='black') axs[3].axvspan(14, 17, alpha=0.1, color='black') axs[3].axvspan(20, 23, alpha=0.1, color='black') axs[3].axvspan(31, 41, alpha=0.1, color='black') for ax in axs: ax.tick_params(axis="y", labelsize=17) plt.xticks(fontsize=16) # axs[1].grid() plt.show()
def compute_table_score(lambdas, capacity_cost, *args, power_rate=2, list_of_nodes=None): data = [] n = args[0].shape[0] Horizon_T = args[0].shape[1] d, b, P_max, P_min, H, h, Mn = args list_of_nodes = list_of_nodes if list_of_nodes is not None else list( range(1, n)) for i_battery in list_of_nodes: print(i_battery) model = price_making_algorithm.run_program( *args, i_battery=i_battery, max_capacity=None, cost_of_battery=capacity_cost, power_rate=power_rate) z_cap_store = pyo.value(model.z_cap) benef = -pyo.value(model.obj) # model.obj = -lambda*u + B*z arbitrage = -pyo.value(model.obj) + capacity_cost * z_cap_store """ test """ model_pt = price_taking_algorithm.run_program(lambdas, i_battery=i_battery, cost_of_battery=0, max_capacity=z_cap_store, power_rate=2) df_pt = pd.DataFrame() # df_pt["u"] = planning planning = [pyo.value(model_pt.u[t]) for t in range(Horizon_T) ] # planning of push and pull from the network expected_profits = sum([ planning[i] * lambdas[10, i] for i in range(Horizon_T) ]) # expected profits (lambda cross u with lambdas as exogenous) df_pt["u"] = planning df_pt["e_profits"] = [ planning[i] * lambdas[10, i] for i in range(Horizon_T) ] df_pt["cumulated e profits"] = df_pt["e_profits"].cumsum() n_lambdas = np.zeros((n, Horizon_T)) # new prices ! for j in range(Horizon_T): """ Here we sell and buy at 0 (i.e we self-schedule_) the quantity devised in the optimization algorithm """ model = economic_dispatch.run_ED_1period(d[:, j], b[:, j], P_max[:, j], P_min[:, j], 0, planning[j], H, h, Mn, i_battery=i_battery) for k in range(d.shape[0]): n_lambdas[k, j] = model.dual[model.injection_definition[k]] actual_profits = sum( [planning[i] * n_lambdas[i_battery, i] for i in range(Horizon_T)]) data.append( [z_cap_store, benef, arbitrage, expected_profits, actual_profits]) df = pd.DataFrame(columns=[ "z_cap", "depreciated profits", "arbitrage only pm", "expected arbitrage pt", "actual arbitrage pt" ], data=data) df["unit arbitrage pt"] = df["expected arbitrage pt"] / df["z_cap"] df["node index"] = list_of_nodes df = df.round(1) df = df[["node index"] + list(df.columns)[:-1]] return df.T