alpacahq / alpacahq/Alpaca-API
Please enable long<->short flipping or target weight orders
- Dominant language
- No language data
- Stars
- 173
- Forks
- 17
- PR merge metrics
- No merged PRs in 30d
Description
**Is your feature request related to a problem? Please describe.**
To convert a long position to short, one must execute 2 trades. My algorithm outputs a target allocation, not a trade, so this forces me to do a bunch of complicated annoying calculations and write a lot of code to await resolution of multiple orders. It'd be easier if you guys did it once, versus all of your customers having to re-implement the stuff
This was working, but then I hit a major issue: alpaca's paper trading system bugged out and recorded equity going super high, then to zero, it seemed like a mess, so I quit using Alpaca for months and just made a custom paper trading thing. I want to give Alpaca another try.
**Describe the solution you'd like**
I wish if I were allocated to a long or short position, I could simply execute a target weight order, and Alpaca would figure out how to allocate that % of my portfolio to the stock. Or, if you can't do target weight orders, then could you at least allow us to automatically flip from long to short or short to long?
**Describe alternatives you've considered**
Well, I stopped using Alpaca months ago.
**Additional context**
here's some free code for you. consider license MIT. Broker is just an abstract class with buy, sell, close, get_weight returns a float for the allocation. etc...
```
# ramda.py
def curry2(fun: Callable) -> any:
@functools.wraps(fun)
def f2(*args, **kwargs):
if len(args) == 0:
return f2
if len(args) == 1:
new_fun: Callable = partial(fun, args[0], **kwargs)
return new_fun
result: any = fun(*args, **kwargs)
return result
return f2
# trade.py
@R.curry2
def check_status(mystatus, id, api=None):
if api is None:
api = get_alpaca()
order = api.get_order(id)._raw
return True if order["status"] == mystatus else False
check_filled = check_status("filled") # pylint: disable: no-value-for-parameter
@R.curry2
def wait_until(status, order_id, api=None, max_wait=env.MAX_WAIT):
if api is None:
api = get_alpaca()
count = 0
while not check_status(status, order_id):
time.sleep(1)
count += 1
if count >= max_wait:
api.cancel_order(order_id)
log.critical("order didn't fill!")
show_order(order_id)
return False
return True
wait_until_filled = wait_until("filled")
# rebalance.py
def rebalance(ticker, target, broker=None):
if broker is None:
broker = get_broker()
# Portfolio (USD, SPY, ...)
# Get number from -1, 1 as output from algorithm for weighting
# 1: 100% Long, -1: 100% Short
# Given current portfolio allocation and desired weighting rank (-1,1)
# Fetch current allocation
# current = (current_quantity * current_price) / portfolio_value
current_price = get_price(ticker=ticker)
current_weight = broker.get_weight(ticker=ticker, price=current_price)
log.info(f"rebalance {ticker} from {current_weight:.02f} to {target:.02f}")
# Execute the buy/sell order to reach allocation
should_close = False
if current_weight < target: # buying
misallocation = target - current_weight
trade = broker.buy
trade_str = "buy"
elif current_weight > target: # selling
misallocation = current_weight - target
trade = broker.sell
trade_str = "sell"
maybe_close_order = ()
if R.sign(current_weight) != R.sign(target): # "cross" the long/short boundary
log.info(f"close the {ticker} position")
close_order = broker.close(ticker)
close_order_filled = broker.wait_until("filled", close_order["id"])
if not close_order_filled:
log.critical(f"couldn't close the {ticker} position. try again")
return (close_order,)
maybe_close_order = (close_order,)
misallocation = target
portfolio_value = broker.get_portfolio_value()
desired_value_change = misallocation * portfolio_value
qty = abs(desired_value_change / current_price)
log.info(trade_str, qty, ticker)
maybe_order = ()
if qty > 1:
order = trade(qty, ticker)
wait_until("filled", order["id"])
maybe_order = (order,)
return tuple(maybe_close_order + maybe_order)
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.