Skip to content

Commit cead2a4

Browse files
committed
Add CLI command to create limit orders
The command allows creating a limit order for a given price (in EUR/MWh) and quantity (in MW). The market side is derived from the sign of the quantity. For now only delivery periods of 15 min and delivery area codes in EUROPE_EIC format are supported. Signed-off-by: cwasicki <[email protected]>
1 parent 6cf69ef commit cead2a4

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

src/frequenz/client/electricity_trading/cli/__main__.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
import click
1111

1212
from frequenz.client.electricity_trading.cli.day_ahead import list_day_ahead_prices
13+
from frequenz.client.electricity_trading.cli.etrading import (
14+
create_order as run_create_order,
15+
)
1316
from frequenz.client.electricity_trading.cli.etrading import (
1417
list_orders as run_list_orders,
1518
)
@@ -54,6 +57,39 @@ def list_orders(url: str, key: str, *, start: datetime, gid: int) -> None:
5457
asyncio.run(run_list_orders(url=url, key=key, delivery_start=start, gid=gid))
5558

5659

60+
@cli.command()
61+
@click.option("--url", required=True, type=str)
62+
@click.option("--key", required=True, type=str)
63+
@click.option("--start", required=True, type=iso)
64+
@click.option("--gid", required=True, type=int)
65+
@click.option("--quantity", required=True, type=str)
66+
@click.option("--price", required=True, type=str)
67+
@click.option("--area", required=True, type=str)
68+
def create_order(
69+
# pylint: disable=too-many-arguments
70+
url: str,
71+
key: str,
72+
*,
73+
start: datetime,
74+
gid: int,
75+
quantity: str,
76+
price: str,
77+
area: str,
78+
) -> None:
79+
"""Create an order."""
80+
asyncio.run(
81+
run_create_order(
82+
url=url,
83+
key=key,
84+
delivery_start=start,
85+
gid=gid,
86+
quantity_mw=quantity,
87+
price_eur=price,
88+
delivery_area=area,
89+
)
90+
)
91+
92+
5793
@cli.command()
5894
@click.option("--entsoe-key", required=True, type=str)
5995
@click.option("--start", default=midnight(), type=iso)

src/frequenz/client/electricity_trading/cli/etrading.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,20 @@
44
"""CLI tool to interact with the trading API."""
55

66
from datetime import datetime, timedelta, timezone
7+
from decimal import Decimal
78
from enum import Enum
89

910
from frequenz.client.electricity_trading import (
1011
Client,
12+
Currency,
13+
DeliveryArea,
1114
DeliveryPeriod,
15+
EnergyMarketCodeType,
16+
MarketSide,
1217
OrderDetail,
18+
OrderType,
19+
Power,
20+
Price,
1321
PublicTrade,
1422
)
1523

@@ -107,6 +115,58 @@ async def list_orders(
107115
print_order(order)
108116

109117

118+
# pylint: disable=too-many-arguments
119+
async def create_order(
120+
url: str,
121+
key: str,
122+
*,
123+
gid: int,
124+
delivery_start: datetime,
125+
delivery_area: str,
126+
price_eur: str,
127+
quantity_mw: str,
128+
) -> None:
129+
"""Create a limit order for a given price (in EUR/MWh) and quantity (in MW).
130+
131+
The market side is determined by the sign of the quantity, positive for buy orders
132+
and negative for sell orders. The delivery period is 15 minutes starting at
133+
`delivery_start`. The delivery area code is expected to be in EUROPE_EIC format.
134+
135+
Args:
136+
url: URL of the trading API.
137+
key: API key.
138+
gid: Gridpool ID.
139+
delivery_start: Start of the delivery period.
140+
delivery_area: Delivery area code.
141+
price_eur: Price in EUR/MWh.
142+
quantity_mw: Quantity in MW, positive for buy orders and negative for sell orders.
143+
"""
144+
client = Client(server_url=url, auth_key=key)
145+
146+
side = MarketSide.SELL if quantity_mw[0] == "-" else MarketSide.BUY
147+
quantity = Power(mw=Decimal(quantity_mw.lstrip("-")))
148+
check_delivery_start(delivery_start)
149+
delivery_period = DeliveryPeriod(
150+
start=delivery_start,
151+
duration=timedelta(minutes=15),
152+
)
153+
order_type = OrderType.LIMIT
154+
price = Price(amount=Decimal(price_eur), currency=Currency.EUR)
155+
del_area = DeliveryArea(
156+
code=delivery_area, code_type=EnergyMarketCodeType.EUROPE_EIC
157+
)
158+
159+
await client.create_gridpool_order(
160+
gridpool_id=gid,
161+
delivery_area=del_area,
162+
delivery_period=delivery_period,
163+
order_type=order_type,
164+
side=side,
165+
price=price,
166+
quantity=quantity,
167+
)
168+
169+
110170
def print_trade_header() -> None:
111171
"""Print trade header in CSV format."""
112172
header = (

0 commit comments

Comments
 (0)