Skip to content

Commit

Permalink
portfolio may not exist
Browse files Browse the repository at this point in the history
  • Loading branch information
Cuizi7 committed Oct 30, 2018
1 parent 2da93ac commit c9d567d
Show file tree
Hide file tree
Showing 15 changed files with 135 additions and 50 deletions.
2 changes: 1 addition & 1 deletion rqalpha/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.2.0
3.2.0.xingye
12 changes: 9 additions & 3 deletions rqalpha/api/api_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from rqalpha.api.api_base import decorate_api_exc, instruments, cal_style
from rqalpha.environment import Environment
from rqalpha.utils.arg_checker import apply_rules, verify_that
from rqalpha.utils.arg_checker import apply_rules, verify_that, verify_env
# noinspection PyUnresolvedReferences
from rqalpha.model.order import LimitOrder, MarketOrder, Order

Expand Down Expand Up @@ -50,7 +50,10 @@ def now_time_str(str_format="%H:%M:%S"):


@export_as_api
@apply_rules(verify_that('quantity').is_number())
@apply_rules(
verify_env().portfolio_exists(),
verify_that('quantity').is_number()
)
def order(order_book_id, quantity, price=None, style=None):
"""
全品种通用智能调仓函数
Expand Down Expand Up @@ -99,7 +102,10 @@ def order(order_book_id, quantity, price=None, style=None):


@export_as_api
@apply_rules(verify_that('quantity').is_number())
@apply_rules(
verify_env().portfolio_exists(),
verify_that('quantity').is_number()
)
def order_to(order_book_id, quantity, price=None, style=None):
"""
全品种通用智能调仓函数
Expand Down
16 changes: 12 additions & 4 deletions rqalpha/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,24 @@ def get_position_model(self, account_type):
def can_submit_order(self, order):
if Environment.get_instance().config.extra.is_hold:
return False
account = self.get_account(order.order_book_id)
try:
account = self.get_account(order.order_book_id)
except NotImplementedError:
account = None
for v in self._frontend_validators:
if not v.can_submit_order(account, order):
if not v.can_submit_order(order, account):
return False
return True

def can_cancel_order(self, order):
if order.is_final():
return False
account = self.get_account(order.order_book_id)
try:
account = self.get_account(order.order_book_id)
except NotImplementedError:
account = None
for v in self._frontend_validators:
if not v.can_cancel_order(account, order):
if not v.can_cancel_order(order, account):
return False
return True

Expand Down Expand Up @@ -166,6 +172,8 @@ def get_account_type(self, order_book_id):
return get_account_type(order_book_id)

def get_account(self, order_book_id):
if not self.portfolio:
raise NotImplementedError
account_type = get_account_type(order_book_id)
return self.portfolio.accounts[account_type]

Expand Down
4 changes: 2 additions & 2 deletions rqalpha/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,12 +644,12 @@ def __subclasshook__(cls, C):

class AbstractFrontendValidator(with_metaclass(abc.ABCMeta)):
@abc.abstractmethod
def can_submit_order(self, account, order):
def can_submit_order(self, order, account=None):
# FIXME: need a better name
raise NotImplementedError

@abc.abstractmethod
def can_cancel_order(self, account, order):
def can_cancel_order(self, order, account=None):
# FIXME: need a better name
raise NotImplementedError

Expand Down
5 changes: 4 additions & 1 deletion rqalpha/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,10 @@ def run(config, source_code=None, user_funcs=None):

broker = env.broker
assert broker is not None
env.portfolio = broker.get_portfolio()
try:
env.portfolio = broker.get_portfolio()
except NotImplementedError:
pass

try:
env.booking = broker.get_booking()
Expand Down
29 changes: 22 additions & 7 deletions rqalpha/mod/rqalpha_mod_sys_accounts/api/api_future.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from rqalpha.execution_context import ExecutionContext
from rqalpha.environment import Environment
from rqalpha.model.order import Order, MarketOrder, LimitOrder, OrderStyle
from rqalpha.const import EXECUTION_PHASE, SIDE, POSITION_EFFECT, ORDER_TYPE, RUN_TYPE
from rqalpha.const import EXECUTION_PHASE, SIDE, POSITION_EFFECT, ORDER_TYPE, RUN_TYPE, POSITION_DIRECTION
from rqalpha.model.instrument import Instrument
from rqalpha.utils import is_valid_price
from rqalpha.utils.exception import RQInvalidArgument
Expand Down Expand Up @@ -79,18 +79,26 @@ def order(id_or_ins, amount, side, position_effect, style):
amount = int(amount)

position = Environment.get_instance().portfolio.positions[order_book_id]
env = Environment.get_instance()

orders = []
if position_effect == POSITION_EFFECT.CLOSE:
if side == SIDE.BUY:
if env.portfolio:
position = env.portfolio.positions[order_book_id]
sell_quantity, sell_old_quantity = position.sell_quantity, position.sell_old_quantity
else:
position = env.booking.get_position(order_book_id, POSITION_DIRECTION.SHORT)
sell_quantity, sell_old_quantity = position.quantity, position.old_quantity

# 如果平仓量大于持仓量,则 Warning 并 取消订单创建
if amount > position.sell_quantity:
if amount > sell_quantity:
user_system_log.warn(
_(u"Order Creation Failed: close amount {amount} is larger than position "
u"quantity {quantity}").format(amount=amount, quantity=position.sell_quantity)
u"quantity {quantity}").format(amount=amount, quantity=sell_quantity)
)
return []
sell_old_quantity = position.sell_old_quantity
sell_old_quantity = sell_old_quantity
if amount > sell_old_quantity:
if sell_old_quantity != 0:
# 如果有昨仓,则创建一个 POSITION_EFFECT.CLOSE 的平仓单
Expand Down Expand Up @@ -119,13 +127,20 @@ def order(id_or_ins, amount, side, position_effect, style):
POSITION_EFFECT.CLOSE
))
else:
if amount > position.buy_quantity:
if env.portfolio:
position = env.portfolio.positions[order_book_id]
buy_quantity, buy_old_quantity = position.buy_quantity, position.buy_old_quantity
else:
position = env.booking.get_position(order_book_id, POSITION_DIRECTION.LONG)
buy_quantity, buy_old_quantity = position.quantity, position.old_quantity

if amount > buy_quantity:
user_system_log.warn(
_(u"Order Creation Failed: close amount {amount} is larger than position "
u"quantity {quantity}").format(amount=amount, quantity=position.buy_quantity)
u"quantity {quantity}").format(amount=amount, quantity=buy_quantity)
)
return []
buy_old_quantity = position.buy_old_quantity
buy_old_quantity = buy_old_quantity
if amount > buy_old_quantity:
if buy_old_quantity != 0:
orders.append(Order.__from_create__(
Expand Down
23 changes: 12 additions & 11 deletions rqalpha/mod/rqalpha_mod_sys_accounts/api/api_stock.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from rqalpha.model.instrument import Instrument
from rqalpha.model.order import Order, MarketOrder, LimitOrder
from rqalpha.utils import is_valid_price
from rqalpha.utils.arg_checker import apply_rules, verify_that
from rqalpha.utils.arg_checker import apply_rules, verify_that, verify_env
# noinspection PyUnresolvedReferences
from rqalpha.utils.exception import patch_user_exc, RQInvalidArgument
from rqalpha.utils.i18n import gettext as _
Expand Down Expand Up @@ -117,12 +117,9 @@ def order_shares(id_or_ins, amount, price=None, style=None):
side = SIDE.SELL
position_effect = POSITION_EFFECT.CLOSE

round_lot = int(env.get_instrument(order_book_id).round_lot)

if side == SIDE.BUY or amount != env.portfolio.accounts[
DEFAULT_ACCOUNT_TYPE.STOCK.name
].positions[order_book_id].sellable:
# 一次性申报卖出时可以卖散股
if side == SIDE.BUY:
# 卖出不再限制 round_lot, order_shares 不再依赖 portfolio
round_lot = int(env.get_instrument(order_book_id).round_lot)
try:
amount = int(Decimal(amount) / Decimal(round_lot)) * round_lot
except ValueError:
Expand Down Expand Up @@ -202,7 +199,8 @@ def order_lots(id_or_ins, amount, price=None, style=None):
EXECUTION_PHASE.ON_TICK,
EXECUTION_PHASE.SCHEDULED,
EXECUTION_PHASE.GLOBAL)
@apply_rules(verify_that('id_or_ins').is_valid_stock(),
@apply_rules(verify_env().portfolio_exists(),
verify_that('id_or_ins').is_valid_stock(),
verify_that('cash_amount').is_number(),
verify_that('style').is_instance_of((MarketOrder, LimitOrder, type(None))))
def order_value(id_or_ins, cash_amount, price=None, style=None):
Expand Down Expand Up @@ -271,7 +269,8 @@ def order_value(id_or_ins, cash_amount, price=None, style=None):
EXECUTION_PHASE.ON_TICK,
EXECUTION_PHASE.SCHEDULED,
EXECUTION_PHASE.GLOBAL)
@apply_rules(verify_that('id_or_ins').is_valid_stock(),
@apply_rules(verify_env().portfolio_exists(),
verify_that('id_or_ins').is_valid_stock(),
verify_that('percent').is_number().is_greater_or_equal_than(-1).is_less_or_equal_than(1),
verify_that('style').is_instance_of((MarketOrder, LimitOrder, type(None))))
def order_percent(id_or_ins, percent, price=None, style=None):
Expand Down Expand Up @@ -310,7 +309,8 @@ def order_percent(id_or_ins, percent, price=None, style=None):
EXECUTION_PHASE.ON_TICK,
EXECUTION_PHASE.SCHEDULED,
EXECUTION_PHASE.GLOBAL)
@apply_rules(verify_that('id_or_ins').is_valid_stock(),
@apply_rules(verify_env().portfolio_exists(),
verify_that('id_or_ins').is_valid_stock(),
verify_that('cash_amount').is_number(),
verify_that('style').is_instance_of((MarketOrder, LimitOrder, type(None))))
def order_target_value(id_or_ins, cash_amount, price=None, style=None):
Expand Down Expand Up @@ -359,7 +359,8 @@ def order_target_value(id_or_ins, cash_amount, price=None, style=None):
EXECUTION_PHASE.ON_TICK,
EXECUTION_PHASE.SCHEDULED,
EXECUTION_PHASE.GLOBAL)
@apply_rules(verify_that('id_or_ins').is_valid_stock(),
@apply_rules(verify_env().portfolio_exists(),
verify_that('id_or_ins').is_valid_stock(),
verify_that('percent').is_number().is_greater_or_equal_than(0).is_less_or_equal_than(1),
verify_that('style').is_instance_of((MarketOrder, LimitOrder, type(None))))
def order_target_percent(id_or_ins, percent, price=None, style=None):
Expand Down
6 changes: 4 additions & 2 deletions rqalpha/mod/rqalpha_mod_sys_risk/validators/cash_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ def _future_validator(self, account, order):
)
return False

def can_submit_order(self, account, order):
def can_submit_order(self, order, account=None):
if account is None:
return True
if account.type == DEFAULT_ACCOUNT_TYPE.STOCK.name:
return self._stock_validator(account, order)
elif account.type == DEFAULT_ACCOUNT_TYPE.FUTURE.name:
return self._future_validator(account, order)
else:
raise NotImplementedError

def can_cancel_order(self, account, order):
def can_cancel_order(self, order, account=None):
return True
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ def _future_validator(account, order):
return False
return True

def can_submit_order(self, account, order):
if account.type == DEFAULT_ACCOUNT_TYPE.FUTURE.name:
def can_submit_order(self, order, account=None):
if account is not None and account.type == DEFAULT_ACCOUNT_TYPE.FUTURE.name:
return self._future_validator(account, order)
return True

def can_cancel_order(self, account, order):
def can_cancel_order(self, order, account=None):
return True
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class IsTradingValidator(AbstractFrontendValidator):
def __init__(self, env):
self._env = env

def can_submit_order(self, account, order):
def can_submit_order(self, order, account=None):
instrument = self._env.data_proxy.instruments(order.order_book_id)
if instrument.listed_date > self._env.trading_dt:
user_system_log.warn(_(u"Order Creation Failed: {order_book_id} is not listed!").format(
Expand Down Expand Up @@ -64,5 +64,5 @@ def can_submit_order(self, account, order):

return True

def can_cancel_order(self, account, order):
def can_cancel_order(self, order, account=None):
return True
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class PriceValidator(AbstractFrontendValidator):
def __init__(self, env):
self._env = env

def can_submit_order(self, account, order):
def can_submit_order(self, order, account=None):
if order.type != ORDER_TYPE.LIMIT:
return True

Expand Down Expand Up @@ -54,5 +54,5 @@ def can_submit_order(self, account, order):

return True

def can_cancel_order(self, account, order):
def can_cancel_order(self, order, account=None):
return True
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ def _stock_validator(account, order):
))
return False

def can_submit_order(self, account, order):
if account.type == DEFAULT_ACCOUNT_TYPE.STOCK.name:
def can_submit_order(self, order, account=None):
if account is not None and account.type == DEFAULT_ACCOUNT_TYPE.STOCK.name:
return self._stock_validator(account, order)
return True

def can_cancel_order(self, account, order):
def can_cancel_order(self, order, account=None):
return True

0 comments on commit c9d567d

Please sign in to comment.