mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-11 14:56:55 +08:00
Merge branch 'main' into main
This commit is contained in:
@@ -49,42 +49,38 @@ class Account:
|
||||
return self.current.position["cash"]
|
||||
|
||||
def update_state_from_order(self, order, trade_val, cost, trade_price):
|
||||
# update cash
|
||||
if order.direction == Order.SELL: # 0 for sell
|
||||
self.current.position["cash"] += trade_val - cost
|
||||
elif order.direction == Order.BUY: # 1 for buy
|
||||
self.current.position["cash"] -= trade_val + cost
|
||||
else:
|
||||
raise NotImplementedError("{} ".format(order.direction))
|
||||
# update turnover
|
||||
self.to += trade_val
|
||||
# update cost
|
||||
self.ct += cost
|
||||
# update return
|
||||
# update self.rtn from order
|
||||
trade_amount = trade_val / trade_price
|
||||
if order.direction == Order.SELL: # 0 for sell
|
||||
# when sell stock, get profit from price change
|
||||
profit = trade_val - self.current.get_stock_price(order.stock_id) * order.deal_amount
|
||||
profit = trade_val - self.current.get_stock_price(order.stock_id) * trade_amount
|
||||
self.rtn += profit # note here do not consider cost
|
||||
elif order.direction == Order.BUY: # 1 for buy
|
||||
# when buy stock, we get return for the rtn computing method
|
||||
# profit in buy order is to make self.rtn is consistent with self.earning at the end of date
|
||||
profit = self.current.get_stock_price(order.stock_id) * order.deal_amount - trade_val
|
||||
profit = self.current.get_stock_price(order.stock_id) * trade_amount - trade_val
|
||||
self.rtn += profit
|
||||
|
||||
def update_order(self, order, trade_val, cost, trade_price):
|
||||
# if stock is sold out, no stock price information in Position, then we should update account first, then update current position
|
||||
# if stock is bought, there is no stock in current position, update current, then update account
|
||||
# The cost will be substracted from the cash at last. So the trading logic can ignore the cost calculation
|
||||
trade_amount = trade_val / trade_price
|
||||
if order.direction == Order.SELL:
|
||||
# sell stock
|
||||
self.update_state_from_order(order, trade_val, cost, trade_price)
|
||||
# update current position
|
||||
# for may sell all of stock_id
|
||||
self.current.update_order(order, trade_price)
|
||||
self.current.update_order(order, trade_val, cost, trade_price)
|
||||
else:
|
||||
# buy stock
|
||||
# deal order, then update state
|
||||
self.current.update_order(order, trade_price)
|
||||
self.current.update_order(order, trade_val, cost, trade_price)
|
||||
self.update_state_from_order(order, trade_val, cost, trade_price)
|
||||
|
||||
def update_daily_end(self, today, trader):
|
||||
|
||||
@@ -208,14 +208,9 @@ class Exchange:
|
||||
# If the order can only be deal 0 trade_val. Nothing to be updated
|
||||
# Otherwise, it will result some stock with 0 amount in the position
|
||||
if trade_account:
|
||||
trade_account.update_order(
|
||||
order=order,
|
||||
trade_val=trade_val,
|
||||
cost=trade_cost,
|
||||
trade_price=trade_price,
|
||||
)
|
||||
trade_account.update_order(order=order, trade_val=trade_val, cost=trade_cost, trade_price=trade_price)
|
||||
elif position:
|
||||
position.update_order(order, trade_price)
|
||||
position.update_order(order=order, trade_val=trade_val, cost=trade_cost, trade_price=trade_price)
|
||||
|
||||
return trade_val, trade_cost, trade_price
|
||||
|
||||
|
||||
@@ -43,38 +43,44 @@ class Position:
|
||||
self.position[stock_id]["price"] = price
|
||||
self.position[stock_id]["weight"] = 0 # update the weight in the end of the trade date
|
||||
|
||||
def buy_stock(self, stock_id, amount, price):
|
||||
def buy_stock(self, stock_id, trade_val, cost, trade_price):
|
||||
trade_amount = trade_val / trade_price
|
||||
if stock_id not in self.position:
|
||||
self.init_stock(stock_id=stock_id, amount=amount, price=price)
|
||||
self.init_stock(stock_id=stock_id, amount=trade_amount, price=trade_price)
|
||||
else:
|
||||
# exist, add amount
|
||||
self.position[stock_id]["amount"] += amount
|
||||
self.position[stock_id]["amount"] += trade_amount
|
||||
|
||||
def sell_stock(self, stock_id, amount):
|
||||
self.position["cash"] -= trade_val + cost
|
||||
|
||||
def sell_stock(self, stock_id, trade_val, cost, trade_price):
|
||||
trade_amount = trade_val / trade_price
|
||||
if stock_id not in self.position:
|
||||
raise KeyError("{} not in current position".format(stock_id))
|
||||
else:
|
||||
# decrease the amount of stock
|
||||
self.position[stock_id]["amount"] -= amount
|
||||
self.position[stock_id]["amount"] -= trade_amount
|
||||
# check if to delete
|
||||
if self.position[stock_id]["amount"] < -1e-5:
|
||||
raise ValueError(
|
||||
"only have {} {}, require {}".format(self.position[stock_id]["amount"], stock_id, amount)
|
||||
"only have {} {}, require {}".format(self.position[stock_id]["amount"], stock_id, trade_amount)
|
||||
)
|
||||
elif abs(self.position[stock_id]["amount"]) <= 1e-5:
|
||||
self.del_stock(stock_id)
|
||||
|
||||
self.position["cash"] += trade_val - cost
|
||||
|
||||
def del_stock(self, stock_id):
|
||||
del self.position[stock_id]
|
||||
|
||||
def update_order(self, order, trade_price):
|
||||
def update_order(self, order, trade_val, cost, trade_price):
|
||||
# handle order, order is a order class, defined in exchange.py
|
||||
if order.direction == Order.BUY:
|
||||
# BUY
|
||||
self.buy_stock(stock_id=order.stock_id, amount=order.deal_amount, price=trade_price)
|
||||
self.buy_stock(order.stock_id, trade_val, cost, trade_price)
|
||||
elif order.direction == Order.SELL:
|
||||
# SELL
|
||||
self.sell_stock(stock_id=order.stock_id, amount=order.deal_amount)
|
||||
self.sell_stock(order.stock_id, trade_val, cost, trade_price)
|
||||
else:
|
||||
raise NotImplementedError("do not suppotr order direction {}".format(order.direction))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user