Added MaximumQuantityElement and MinimumQuantityElement.
This commit is contained in:
parent
06bd490652
commit
e3f1939287
33
.envrc
33
.envrc
|
@ -2,3 +2,36 @@ CURRENT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||
|
||||
export PATH=$PATH:$CURRENT_DIRECTORY/bin:$CURRENT_DIRECTORY/scripts
|
||||
|
||||
# Automatically set up our virtual environment in .venv (same as poetry is configured to use).
|
||||
# From: https://github.com/direnv/direnv/wiki/Python
|
||||
realpath() {
|
||||
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
|
||||
}
|
||||
layout_python-venv() {
|
||||
local python=${1:-python3}
|
||||
[[ $# -gt 0 ]] && shift
|
||||
unset PYTHONHOME
|
||||
if [[ -n $VIRTUAL_ENV ]]; then
|
||||
VIRTUAL_ENV=$(realpath "${VIRTUAL_ENV}")
|
||||
else
|
||||
local python_version
|
||||
python_version=$("$python" -c "import platform; print(platform.python_version())")
|
||||
if [[ -z $python_version ]]; then
|
||||
log_error "Could not detect Python version"
|
||||
return 1
|
||||
fi
|
||||
VIRTUAL_ENV=$PWD/.direnv/python-venv-$python_version
|
||||
fi
|
||||
export VIRTUAL_ENV
|
||||
if [[ ! -d $VIRTUAL_ENV ]]; then
|
||||
log_status "no venv found; creating $VIRTUAL_ENV"
|
||||
"$python" -m venv "$VIRTUAL_ENV"
|
||||
fi
|
||||
|
||||
PATH="${VIRTUAL_ENV}/bin:${PATH}"
|
||||
export PATH
|
||||
}
|
||||
|
||||
export VIRTUAL_ENV=.venv
|
||||
|
||||
layout python-venv
|
||||
|
|
|
@ -237,6 +237,26 @@ The result is if you specify `--fixedspread-value 2 --fixedspread-value 4` the B
|
|||
Note that one consequence of this processing of `Order`s is that the orders returned from this `Element` may be in a different sort-order to the orders that were sent to it.
|
||||
|
||||
|
||||
### `MaximumQuantityElement`
|
||||
|
||||
> Specified using: `--chain maximumquantity`
|
||||
|
||||
> Accepts parameter: `--maximumquantity-size`
|
||||
|
||||
> Accepts parameter: `--maximumquantity-remove`
|
||||
|
||||
Ensures orders' quantities are always less than the maximum. Will either:
|
||||
* Remove the order if the position size is too high, or
|
||||
* Set the too-high position size to the permitted maximum
|
||||
|
||||
This `Element` examines every order to make sure the order quantity is less than or equal to the `--maximumquantity-size`. If it is less, this `Element` takes no further action on it.
|
||||
|
||||
If the order quantity is greater than `--maximumquantity-size`, then either:
|
||||
|
||||
1. (default) the order quantity will be reduced to the value specified by `--maximumquantity-size`.
|
||||
2. (if `--maximumquantity-remove` is specified) the order will be removed from further processing and so will not be placed.
|
||||
|
||||
|
||||
### `MinimumChargeElement`
|
||||
|
||||
> Specified using: `--chain minimumcharge`
|
||||
|
@ -267,6 +287,26 @@ The result is if you specify `--minimumcharge-ratio 2 --minimumcharge-ratio 4` t
|
|||
Note that one consequence of this processing of `Order`s is that the orders returned from this `Element` may be in a different sort-order to the orders that were sent to it.
|
||||
|
||||
|
||||
### `MinimumQuantityElement`
|
||||
|
||||
> Specified using: `--chain minimumquantity`
|
||||
|
||||
> Accepts parameter: `--minimumquantity-size`
|
||||
|
||||
> Accepts parameter: `--minimumquantity-remove`
|
||||
|
||||
Ensures orders' quantities are always greater than the minimum. Will either:
|
||||
* Remove the order if the position size is too low, or
|
||||
* Set the too-low position size to the permitted minimum
|
||||
|
||||
This `Element` examines every order to make sure the order quantity is greater than or equal to the `--minimumquantity-size`. If it is greater, this `Element` takes no further action on it.
|
||||
|
||||
If the order quantity is less than `--minimumquantity-size`, then either:
|
||||
|
||||
1. (default) the order quantity will be increased to the value specified by `--minimumquantity-size`.
|
||||
2. (if `--minimumquantity-remove` is specified) the order will be removed from further processing and so will not be placed.
|
||||
|
||||
|
||||
### `PreventPostOnlyCrossingBookElement`
|
||||
|
||||
> Specified using `--chain preventpostonlycrossingbook`
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
# [Email](mailto:hello@blockworks.foundation)
|
||||
|
||||
import argparse
|
||||
|
||||
import mango
|
||||
import typing
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ from .confidenceintervalelement import ConfidenceIntervalElement
|
|||
from .element import Element
|
||||
from .fixedpositionsizeelement import FixedPositionSizeElement
|
||||
from .fixedspreadelement import FixedSpreadElement
|
||||
from .maximumquantityelement import MaximumQuantityElement
|
||||
from .minimumquantityelement import MinimumQuantityElement
|
||||
from .minimumchargeelement import MinimumChargeElement
|
||||
from .preventpostonlycrossingbookelement import PreventPostOnlyCrossingBookElement
|
||||
from .quotesinglesideelement import QuoteSingleSideElement
|
||||
|
@ -59,6 +61,8 @@ class ChainBuilder:
|
|||
ConfidenceIntervalElement.add_command_line_parameters(parser)
|
||||
FixedSpreadElement.add_command_line_parameters(parser)
|
||||
FixedPositionSizeElement.add_command_line_parameters(parser)
|
||||
MaximumQuantityElement.add_command_line_parameters(parser)
|
||||
MinimumQuantityElement.add_command_line_parameters(parser)
|
||||
MinimumChargeElement.add_command_line_parameters(parser)
|
||||
PreventPostOnlyCrossingBookElement.add_command_line_parameters(parser)
|
||||
QuoteSingleSideElement.add_command_line_parameters(parser)
|
||||
|
@ -100,8 +104,12 @@ class ChainBuilder:
|
|||
return FixedSpreadElement.from_command_line_parameters(args)
|
||||
elif proper_name == "FIXEDPOSITIONSIZE":
|
||||
return FixedPositionSizeElement.from_command_line_parameters(args)
|
||||
elif proper_name == "MAXIMUMQUANTITY":
|
||||
return MaximumQuantityElement.from_command_line_parameters(args)
|
||||
elif proper_name == "MINIMUMCHARGE":
|
||||
return MinimumChargeElement.from_command_line_parameters(args)
|
||||
elif proper_name == "MINIMUMQUANTITY":
|
||||
return MinimumQuantityElement.from_command_line_parameters(args)
|
||||
elif proper_name == "PREVENTPOSTONLYCROSSINGBOOK":
|
||||
return PreventPostOnlyCrossingBookElement.from_command_line_parameters(args)
|
||||
elif proper_name == "QUOTESINGLESIDE":
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
# # ⚠ Warning
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# [🥭 Mango Markets](https://mango.markets/) support is available at:
|
||||
# [Docs](https://docs.mango.markets/)
|
||||
# [Discord](https://discord.gg/67jySBhxrg)
|
||||
# [Twitter](https://twitter.com/mangomarkets)
|
||||
# [Github](https://github.com/blockworks-foundation)
|
||||
# [Email](mailto:hello@blockworks.foundation)
|
||||
|
||||
import argparse
|
||||
import mango
|
||||
import typing
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from .element import Element
|
||||
from ...modelstate import ModelState
|
||||
|
||||
|
||||
# # 🥭 MaximumQuantityElement class
|
||||
#
|
||||
# Ensures orders' quantities are always less than the maximum. Will either:
|
||||
# * Remove the order if the position size is too high, or
|
||||
# * Set the too-high position size to the permitted maximum
|
||||
#
|
||||
class MaximumQuantityElement(Element):
|
||||
def __init__(self, maximum_quantity: Decimal, remove: bool = False) -> None:
|
||||
super().__init__()
|
||||
self.maximum_quantity: Decimal = maximum_quantity
|
||||
self.remove: bool = remove
|
||||
|
||||
@staticmethod
|
||||
def add_command_line_parameters(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument("--maximumquantity-size", type=Decimal, default=Decimal(1),
|
||||
help="the maximum permitted order quantity")
|
||||
parser.add_argument("--maximumquantity-remove", action="store_true", default=False,
|
||||
help="remove an order that has too big a quantity (default is to reduce order quantity to maximum)")
|
||||
|
||||
@staticmethod
|
||||
def from_command_line_parameters(args: argparse.Namespace) -> "MaximumQuantityElement":
|
||||
return MaximumQuantityElement(args.maximumquantity_size, args.maximumquantity_remove)
|
||||
|
||||
def process(self, context: mango.Context, model_state: ModelState, orders: typing.Sequence[mango.Order]) -> typing.Sequence[mango.Order]:
|
||||
new_orders: typing.List[mango.Order] = []
|
||||
for order in orders:
|
||||
if order.quantity < self.maximum_quantity:
|
||||
new_orders += [order]
|
||||
else:
|
||||
if self.remove:
|
||||
self.logger.debug(f"""Order change - order quantity is greater than maximum of {self.maximum_quantity} so removing:
|
||||
Old: {order}
|
||||
New: None""")
|
||||
else:
|
||||
new_order: mango.Order = order.with_quantity(self.maximum_quantity)
|
||||
self.logger.debug(f"""Order change - order quantity is greater than maximum of {self.maximum_quantity} so changing order quantity to {self.maximum_quantity}:
|
||||
Old: {order}
|
||||
New: {new_order}""")
|
||||
new_orders += [new_order]
|
||||
|
||||
return new_orders
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"« 𝙼𝚊𝚡𝚒𝚖𝚞𝚖𝚀𝚞𝚊𝚗𝚝𝚒𝚝𝚢𝙴𝚕𝚎𝚖𝚎𝚗𝚝 [maximum quantity: {self.maximum_quantity}, remove: {self.remove}] »"
|
|
@ -0,0 +1,69 @@
|
|||
# # ⚠ Warning
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# [🥭 Mango Markets](https://mango.markets/) support is available at:
|
||||
# [Docs](https://docs.mango.markets/)
|
||||
# [Discord](https://discord.gg/67jySBhxrg)
|
||||
# [Twitter](https://twitter.com/mangomarkets)
|
||||
# [Github](https://github.com/blockworks-foundation)
|
||||
# [Email](mailto:hello@blockworks.foundation)
|
||||
|
||||
import argparse
|
||||
import mango
|
||||
import typing
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from .element import Element
|
||||
from ...modelstate import ModelState
|
||||
|
||||
|
||||
# # 🥭 MinimumQuantityElement class
|
||||
#
|
||||
# Ensures orders' quantities are always greater than the minimum. Will either:
|
||||
# * Remove the order if the position size is too low, or
|
||||
# * Set the too-low position size to the permitted minimum
|
||||
#
|
||||
class MinimumQuantityElement(Element):
|
||||
def __init__(self, minimum_quantity: Decimal, remove: bool = False) -> None:
|
||||
super().__init__()
|
||||
self.minimum_quantity: Decimal = minimum_quantity
|
||||
self.remove: bool = remove
|
||||
|
||||
@staticmethod
|
||||
def add_command_line_parameters(parser: argparse.ArgumentParser) -> None:
|
||||
parser.add_argument("--minimumquantity-size", type=Decimal, default=Decimal(1),
|
||||
help="the minimum permitted quantity")
|
||||
parser.add_argument("--minimumquantity-remove", action="store_true", default=False,
|
||||
help="remove an order that has too small a quantity (default is to increase order quantity to minimum)")
|
||||
|
||||
@staticmethod
|
||||
def from_command_line_parameters(args: argparse.Namespace) -> "MinimumQuantityElement":
|
||||
return MinimumQuantityElement(args.minimumquantity_size, args.minimumquantity_remove)
|
||||
|
||||
def process(self, context: mango.Context, model_state: ModelState, orders: typing.Sequence[mango.Order]) -> typing.Sequence[mango.Order]:
|
||||
new_orders: typing.List[mango.Order] = []
|
||||
for order in orders:
|
||||
if order.quantity > self.minimum_quantity:
|
||||
new_orders += [order]
|
||||
else:
|
||||
if self.remove:
|
||||
self.logger.debug(f"""Order change - order quantity is less than minimum of {self.minimum_quantity} so removing:
|
||||
Old: {order}
|
||||
New: None""")
|
||||
else:
|
||||
new_order: mango.Order = order.with_quantity(self.minimum_quantity)
|
||||
self.logger.debug(f"""Order change - order quantity is less than minimum of {self.minimum_quantity} so changing order quantity to {self.minimum_quantity}:
|
||||
Old: {order}
|
||||
New: {new_order}""")
|
||||
new_orders += [new_order]
|
||||
|
||||
return new_orders
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"« 𝙼𝚒𝚗𝚒𝚖𝚞𝚖𝚀𝚞𝚊𝚗𝚝𝚒𝚝𝚢𝙴𝚕𝚎𝚖𝚎𝚗𝚝 [minimum quantity: {self.minimum_quantity}, remove: {self.remove}] »"
|
|
@ -14,7 +14,6 @@
|
|||
# [Email](mailto:hello@blockworks.foundation)
|
||||
|
||||
import argparse
|
||||
|
||||
import mango
|
||||
import typing
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
import argparse
|
||||
import typing
|
||||
|
||||
from ...context import mango
|
||||
from ...fakes import fake_context, fake_model_state, fake_order
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from mango.marketmaking.orderchain.maximumquantityelement import MaximumQuantityElement
|
||||
|
||||
bids: typing.Sequence[mango.Order] = [
|
||||
fake_order(price=Decimal(78), quantity=Decimal(1), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(77), quantity=Decimal(2), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(76), quantity=Decimal(1), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(75), quantity=Decimal(5), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(74), quantity=Decimal(3), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(73), quantity=Decimal(7), side=mango.Side.BUY)
|
||||
]
|
||||
asks: typing.Sequence[mango.Order] = [
|
||||
fake_order(price=Decimal(82), quantity=Decimal(3), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(83), quantity=Decimal(1), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(84), quantity=Decimal(1), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(85), quantity=Decimal(3), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(86), quantity=Decimal(3), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(87), quantity=Decimal(7), side=mango.Side.SELL)
|
||||
]
|
||||
orderbook: mango.OrderBook = mango.OrderBook("TEST", bids, asks)
|
||||
model_state = fake_model_state(orderbook=orderbook)
|
||||
|
||||
|
||||
def test_from_args() -> None:
|
||||
args: argparse.Namespace = argparse.Namespace(
|
||||
maximumquantity_size=Decimal(7),
|
||||
maximumquantity_remove=True)
|
||||
actual: MaximumQuantityElement = MaximumQuantityElement.from_command_line_parameters(args)
|
||||
assert actual is not None
|
||||
assert actual.maximum_quantity == 7
|
||||
assert actual.remove
|
||||
|
||||
|
||||
def test_low_buy_not_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(75), quantity=Decimal(7), side=mango.Side.BUY)
|
||||
|
||||
actual: MaximumQuantityElement = MaximumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0] == order
|
||||
|
||||
|
||||
def test_high_buy_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(75), quantity=Decimal(17), side=mango.Side.BUY)
|
||||
|
||||
actual: MaximumQuantityElement = MaximumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0].quantity == 10
|
||||
|
||||
|
||||
def test_high_buy_removed() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(75), quantity=Decimal(17), side=mango.Side.BUY)
|
||||
|
||||
actual: MaximumQuantityElement = MaximumQuantityElement(Decimal(10), True)
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
|
||||
def test_low_sell_not_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(85), quantity=Decimal(6), side=mango.Side.SELL)
|
||||
|
||||
actual: MaximumQuantityElement = MaximumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0] == order
|
||||
|
||||
|
||||
def test_high_sell_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(85), quantity=Decimal(16), side=mango.Side.SELL)
|
||||
|
||||
actual: MaximumQuantityElement = MaximumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0].quantity == 10
|
||||
|
||||
|
||||
def test_high_sell_removed() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(85), quantity=Decimal(16), side=mango.Side.SELL)
|
||||
|
||||
actual: MaximumQuantityElement = MaximumQuantityElement(Decimal(10), True)
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert len(result) == 0
|
|
@ -0,0 +1,98 @@
|
|||
import argparse
|
||||
import typing
|
||||
|
||||
from ...context import mango
|
||||
from ...fakes import fake_context, fake_model_state, fake_order
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from mango.marketmaking.orderchain.minimumquantityelement import MinimumQuantityElement
|
||||
|
||||
bids: typing.Sequence[mango.Order] = [
|
||||
fake_order(price=Decimal(78), quantity=Decimal(1), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(77), quantity=Decimal(2), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(76), quantity=Decimal(1), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(75), quantity=Decimal(5), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(74), quantity=Decimal(3), side=mango.Side.BUY),
|
||||
fake_order(price=Decimal(73), quantity=Decimal(7), side=mango.Side.BUY)
|
||||
]
|
||||
asks: typing.Sequence[mango.Order] = [
|
||||
fake_order(price=Decimal(82), quantity=Decimal(3), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(83), quantity=Decimal(1), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(84), quantity=Decimal(1), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(85), quantity=Decimal(3), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(86), quantity=Decimal(3), side=mango.Side.SELL),
|
||||
fake_order(price=Decimal(87), quantity=Decimal(7), side=mango.Side.SELL)
|
||||
]
|
||||
orderbook: mango.OrderBook = mango.OrderBook("TEST", bids, asks)
|
||||
model_state = fake_model_state(orderbook=orderbook)
|
||||
|
||||
|
||||
def test_from_args() -> None:
|
||||
args: argparse.Namespace = argparse.Namespace(
|
||||
minimumquantity_size=Decimal(7),
|
||||
minimumquantity_remove=True)
|
||||
actual: MinimumQuantityElement = MinimumQuantityElement.from_command_line_parameters(args)
|
||||
assert actual is not None
|
||||
assert actual.minimum_quantity == 7
|
||||
assert actual.remove
|
||||
|
||||
|
||||
def test_high_buy_not_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(75), quantity=Decimal(20), side=mango.Side.BUY)
|
||||
|
||||
actual: MinimumQuantityElement = MinimumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0] == order
|
||||
|
||||
|
||||
def test_low_buy_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(75), quantity=Decimal(7), side=mango.Side.BUY)
|
||||
|
||||
actual: MinimumQuantityElement = MinimumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0].quantity == 10
|
||||
|
||||
|
||||
def test_low_buy_removed() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(75), quantity=Decimal(7), side=mango.Side.BUY)
|
||||
|
||||
actual: MinimumQuantityElement = MinimumQuantityElement(Decimal(10), True)
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert len(result) == 0
|
||||
|
||||
|
||||
def test_high_sell_not_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(85), quantity=Decimal(16), side=mango.Side.SELL)
|
||||
|
||||
actual: MinimumQuantityElement = MinimumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0] == order
|
||||
|
||||
|
||||
def test_low_sell_updated() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(85), quantity=Decimal(6), side=mango.Side.SELL)
|
||||
|
||||
actual: MinimumQuantityElement = MinimumQuantityElement(Decimal(10))
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert result[0].quantity == 10
|
||||
|
||||
|
||||
def test_low_sell_removed() -> None:
|
||||
context = fake_context()
|
||||
order: mango.Order = fake_order(price=Decimal(85), quantity=Decimal(6), side=mango.Side.SELL)
|
||||
|
||||
actual: MinimumQuantityElement = MinimumQuantityElement(Decimal(10), True)
|
||||
result = actual.process(context, model_state, [order])
|
||||
|
||||
assert len(result) == 0
|
|
@ -55,7 +55,7 @@ def test_ask_price_updated() -> None:
|
|||
assert result[0].price == 81
|
||||
|
||||
|
||||
def test_accumulation_ignores_own_orders_updated() -> None:
|
||||
def test_top_check_ignores_own_orders_updated() -> None:
|
||||
order_owner: PublicKey = fake_seeded_public_key("order owner")
|
||||
bids: typing.Sequence[mango.Order] = [
|
||||
fake_order(price=Decimal(78), quantity=Decimal(1), side=mango.Side.BUY).with_owner(order_owner),
|
||||
|
|
Loading…
Reference in New Issue