Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Feature: support selling short #1736

Closed
Expand Up @@ -940,6 +940,7 @@ public class Messages extends NLS
public static String SecurityMenuAddPrice;
public static String SecurityMenuBuy;
public static String SecurityMenuConfigureOnlineUpdate;
public static String SecurityMenuCover;
public static String SecurityMenuCreateManually;
public static String SecurityMenuCreateQuotesFromTransactions;
public static String SecurityMenuDebugGetHistoricalQuotes;
Expand All @@ -960,6 +961,7 @@ public class Messages extends NLS
public static String SecurityMenuRemoveFromWatchlist;
public static String SecurityMenuSearch4Securities;
public static String SecurityMenuSell;
public static String SecurityMenuShort;
public static String SecurityMenuStockSplit;
public static String SecurityMenuAddEvent;
public static String SecurityMenuTransfer;
Expand Down
Expand Up @@ -120,6 +120,8 @@ public List<Element> getElements()
for (final PortfolioTransaction.Type type : EnumSet.of( //
PortfolioTransaction.Type.BUY, //
PortfolioTransaction.Type.SELL, //
PortfolioTransaction.Type.COVER, //
PortfolioTransaction.Type.SHORT, //
PortfolioTransaction.Type.DELIVERY_INBOUND, //
PortfolioTransaction.Type.DELIVERY_OUTBOUND))
{
Expand Down
Expand Up @@ -604,9 +604,11 @@ protected long calculateConvertedGrossValue()
switch (type)
{
case BUY:
case COVER:
case DELIVERY_INBOUND:
return Math.max(0, total - feesAndTaxes);
case SELL:
case SHORT:
case DELIVERY_OUTBOUND:
return total + feesAndTaxes;
default:
Expand All @@ -621,9 +623,11 @@ private long calculateTotal()
switch (type)
{
case BUY:
case COVER:
case DELIVERY_INBOUND:
return convertedGrossValue + feesAndTaxes;
case SELL:
case SHORT:
case DELIVERY_OUTBOUND:
return Math.max(0, convertedGrossValue - feesAndTaxes);
default:
Expand Down
Expand Up @@ -411,6 +411,8 @@ private String getTotalLabel() // NOSONAR
return Messages.ColumnCreditNote;
case BUY:
case SELL:
case COVER:
case SHORT:
case TRANSFER_IN:
case TRANSFER_OUT:
default:
Expand Down
Expand Up @@ -92,6 +92,8 @@ private void checkType()
return;
case BUY:
case SELL:
case COVER:
case SHORT:
case TRANSFER_IN:
case TRANSFER_OUT:
default:
Expand Down
Expand Up @@ -28,7 +28,10 @@ public BuySellModel(Client client, PortfolioTransaction.Type type)
@Override
public boolean accepts(PortfolioTransaction.Type type)
{
return type == PortfolioTransaction.Type.BUY || type == PortfolioTransaction.Type.SELL;
return type == PortfolioTransaction.Type.BUY
|| type == PortfolioTransaction.Type.SELL
|| type == PortfolioTransaction.Type.COVER
|| type == PortfolioTransaction.Type.SHORT;
}

@Override
Expand Down
Expand Up @@ -59,7 +59,10 @@ public SecurityTransactionDialog(@Named(IServiceConstants.ACTIVE_SHELL) Shell pa
@PostConstruct
private void createModel(ExchangeRateProviderFactory factory, PortfolioTransaction.Type type) // NOSONAR
{
boolean isBuySell = type == PortfolioTransaction.Type.BUY || type == PortfolioTransaction.Type.SELL;
boolean isBuySell = type == PortfolioTransaction.Type.BUY
|| type == PortfolioTransaction.Type.SELL
|| type == PortfolioTransaction.Type.COVER
|| type == PortfolioTransaction.Type.SHORT;
AbstractSecurityTransactionModel model = isBuySell ? new BuySellModel(client, type)
: new SecurityDeliveryModel(client, type);
model.setExchangeRateProviderFactory(factory);
Expand Down Expand Up @@ -289,9 +292,11 @@ private String sign()
switch (model().getType())
{
case BUY:
case COVER:
case DELIVERY_INBOUND:
return "+ "; //$NON-NLS-1$
case SELL:
case SHORT:
case DELIVERY_OUTBOUND:
return "- "; //$NON-NLS-1$
default:
Expand All @@ -304,10 +309,12 @@ private String getTotalLabel()
switch (model().getType())
{
case BUY:
case COVER:
return Messages.ColumnDebitNote;
case DELIVERY_INBOUND:
return Messages.LabelValueInboundDelivery;
case SELL:
case SHORT:
return Messages.ColumnCreditNote;
case DELIVERY_OUTBOUND:
return Messages.LabelValueOutboundDelivery;
Expand Down
Expand Up @@ -42,6 +42,8 @@ public void aboutToShow(@Named(IServiceConstants.ACTIVE_PART) MPart part, List<M

items.add(create(portfolioPart, SecurityTransactionDialog.class, PortfolioTransaction.Type.BUY));
items.add(create(portfolioPart, SecurityTransactionDialog.class, PortfolioTransaction.Type.SELL));
items.add(create(portfolioPart, SecurityTransactionDialog.class, PortfolioTransaction.Type.SHORT));
items.add(create(portfolioPart, SecurityTransactionDialog.class, PortfolioTransaction.Type.COVER));
items.add(create(portfolioPart, SecurityTransactionDialog.class, PortfolioTransaction.Type.DELIVERY_INBOUND));
items.add(create(portfolioPart, SecurityTransactionDialog.class, PortfolioTransaction.Type.DELIVERY_OUTBOUND));

Expand Down
Expand Up @@ -1902,6 +1902,8 @@ SecurityMenuBuy = Buy

SecurityMenuConfigureOnlineUpdate = Configure online update...

SecurityMenuCover = Cover

SecurityMenuCreateManually = Create manually...

SecurityMenuCreateQuotesFromTransactions = Create historical quotes from transactions
Expand Down Expand Up @@ -1942,6 +1944,8 @@ SecurityMenuSearch4Securities = Search for instruments...

SecurityMenuSell = Sell

SecurityMenuShort = Short

SecurityMenuStockSplit = Stock split...

SecurityMenuTransfer = Transfer...
Expand Down
Expand Up @@ -67,12 +67,24 @@ public class TransactionTypeEditingSupport extends ColumnEditingSupport
PortfolioTransaction.Type.DELIVERY_OUTBOUND, PortfolioTransaction.Type.BUY,
new Class[] { RevertDeliveryAction.class, ConvertDeliveryToBuySellAction.class },

PortfolioTransaction.Type.SHORT, PortfolioTransaction.Type.COVER,
new Class[] { RevertBuySellAction.class },

PortfolioTransaction.Type.COVER, PortfolioTransaction.Type.SHORT,
new Class[] { RevertBuySellAction.class },

AccountTransaction.Type.SELL, AccountTransaction.Type.BUY,
new Class[] { RevertBuySellAction.class },

AccountTransaction.Type.BUY, AccountTransaction.Type.SELL,
new Class[] { RevertBuySellAction.class },

AccountTransaction.Type.SHORT, AccountTransaction.Type.COVER,
new Class[] { RevertBuySellAction.class },

AccountTransaction.Type.COVER, AccountTransaction.Type.SHORT,
new Class[] { RevertBuySellAction.class },

AccountTransaction.Type.TRANSFER_IN, AccountTransaction.Type.TRANSFER_OUT,
new Class[] { RevertTransferAction.class },

Expand Down
Expand Up @@ -89,6 +89,20 @@ public void menuAboutToShow(IMenuManager manager, final Account account, final S
.with(security) //
.addTo(manager);

new OpenDialogAction(owner, Messages.SecurityMenuCover + "...") //$NON-NLS-1$
.type(SecurityTransactionDialog.class) //
.parameters(PortfolioTransaction.Type.COVER) //
.with(portfolio[0]) //
.with(security) //
.addTo(manager);

new OpenDialogAction(owner, Messages.SecurityMenuShort + "...") //$NON-NLS-1$
.type(SecurityTransactionDialog.class) //
.parameters(PortfolioTransaction.Type.SHORT) //
.with(portfolio[0]) //
.with(security) //
.addTo(manager);

new OpenDialogAction(owner, Messages.SecurityMenuDividends + "...") //$NON-NLS-1$
.type(AccountTransactionDialog.class) //
.parameters(AccountTransaction.Type.DIVIDENDS) //
Expand Down
Expand Up @@ -790,6 +790,7 @@ private void updateBalance(Account account)
case DIVIDENDS:
case TAX_REFUND:
case SELL:
case SHORT:
case TRANSFER_IN:
case FEES_REFUND:
balance.add(t.getMonetaryAmount());
Expand All @@ -799,6 +800,7 @@ private void updateBalance(Account account)
case INTEREST_CHARGE:
case TAXES:
case BUY:
case COVER:
case TRANSFER_OUT:
balance.subtract(t.getMonetaryAmount());
break;
Expand Down
Expand Up @@ -163,14 +163,13 @@ public Object function(Object[] arguments)
JSColors colors = new JSColors();

snapshot.getAssetPositions() //
.filter(p -> p.getValuation().getAmount() > 0) //
.sorted((l, r) -> Long.compare(r.getValuation().getAmount(),
l.getValuation().getAmount())) //
.forEach(p -> {
String name = JSONObject.escape(p.getDescription());
String percentage = Values.Percent2.format(p.getShare());
joiner.add(String.format(ENTRY, name, //
p.getValuation().getAmount(), //
Math.abs(p.getValuation().getAmount()), //
colors.next(), //
name, percentage, Values.Share.format(p.getPosition().getShares()), //
Values.Money.format(p.getValuation()
Expand Down
Expand Up @@ -925,6 +925,7 @@ private void addInvestmentMarkerLines(ChartInterval chartInterval)
List<PortfolioTransaction> purchase = client.getPortfolios().stream().flatMap(p -> p.getTransactions().stream())
.filter(t -> t.getSecurity() == security)
.filter(t -> t.getType() == PortfolioTransaction.Type.BUY
|| t.getType() == PortfolioTransaction.Type.COVER
|| t.getType() == PortfolioTransaction.Type.DELIVERY_INBOUND)
.filter(t -> chartInterval.contains(t.getDateTime())) //
.sorted(new Transaction.ByDate()).collect(Collectors.toList());
Expand All @@ -934,6 +935,7 @@ private void addInvestmentMarkerLines(ChartInterval chartInterval)
List<PortfolioTransaction> sales = client.getPortfolios().stream().flatMap(p -> p.getTransactions().stream())
.filter(t -> t.getSecurity() == security)
.filter(t -> t.getType() == PortfolioTransaction.Type.SELL
|| t.getType() == PortfolioTransaction.Type.SHORT
|| t.getType() == PortfolioTransaction.Type.DELIVERY_OUTBOUND)
.filter(t -> chartInterval.contains(t.getDateTime())) //
.sorted(new Transaction.ByDate()).collect(Collectors.toList());
Expand Down
Expand Up @@ -904,6 +904,18 @@ private void fillTransactionContextMenu(IMenuManager manager, Security security)
.with(security) //
.addTo(manager);

new OpenDialogAction(view, Messages.SecurityMenuCover + "...") //$NON-NLS-1$
.type(SecurityTransactionDialog.class) //
.parameters(PortfolioTransaction.Type.COVER) //
.with(security) //
.addTo(manager);

new OpenDialogAction(view, Messages.SecurityMenuShort + "...") //$NON-NLS-1$
.type(SecurityTransactionDialog.class) //
.parameters(PortfolioTransaction.Type.SHORT) //
.with(security) //
.addTo(manager);

new OpenDialogAction(view, Messages.SecurityMenuDividends + "...") //$NON-NLS-1$
.type(AccountTransactionDialog.class) //
.parameters(AccountTransaction.Type.DIVIDENDS) //
Expand Down
Expand Up @@ -64,6 +64,20 @@ public void menuAboutToShow(IMenuManager manager, final Security security, final
.with(security) //
.addTo(manager);

new OpenDialogAction(owner, Messages.SecurityMenuCover + "...") //$NON-NLS-1$
.type(SecurityTransactionDialog.class) //
.parameters(PortfolioTransaction.Type.COVER) //
.with(portfolio) //
.with(security) //
.addTo(manager);

new OpenDialogAction(owner, Messages.SecurityMenuShort + "...") //$NON-NLS-1$
.type(SecurityTransactionDialog.class) //
.parameters(PortfolioTransaction.Type.SHORT) //
.with(portfolio) //
.with(security) //
.addTo(manager);

new OpenDialogAction(owner, Messages.SecurityMenuDividends + "...") //$NON-NLS-1$
.type(AccountTransactionDialog.class) //
.parameters(AccountTransaction.Type.DIVIDENDS) //
Expand Down
Expand Up @@ -250,9 +250,11 @@ private long getSharesHeld(Client client, Security security)
switch (t.getType())
{
case BUY:
case COVER:
case DELIVERY_INBOUND:
return t.getShares();
case SELL:
case SHORT:
case DELIVERY_OUTBOUND:
return -t.getShares();
default:
Expand Down
Expand Up @@ -550,7 +550,9 @@ private void fillContextMenuPortfolioTxList(IMenuManager manager, IStructuredSel
PortfolioTransaction ptx = tx.getTransaction();

allBuyOrSellType &= ptx.getType() == PortfolioTransaction.Type.BUY
|| ptx.getType() == PortfolioTransaction.Type.SELL;
|| ptx.getType() == PortfolioTransaction.Type.SELL
|| ptx.getType() == PortfolioTransaction.Type.COVER
|| ptx.getType() == PortfolioTransaction.Type.SHORT;

allDelivery &= ptx.getType() == PortfolioTransaction.Type.DELIVERY_INBOUND
|| ptx.getType() == PortfolioTransaction.Type.DELIVERY_OUTBOUND;
Expand Down
Expand Up @@ -25,14 +25,20 @@ public RevertBuySellAction(Client client, TransactionPair<?> transaction)
{
PortfolioTransaction.Type type = ((PortfolioTransaction) transaction.getTransaction()).getType();

if (type != PortfolioTransaction.Type.BUY && type != PortfolioTransaction.Type.SELL)
if (type != PortfolioTransaction.Type.BUY
&& type != PortfolioTransaction.Type.SELL
&& type != PortfolioTransaction.Type.COVER
&& type != PortfolioTransaction.Type.SHORT)
throw new IllegalArgumentException();
}
else if (transaction.getTransaction() instanceof AccountTransaction)
{
AccountTransaction.Type type = ((AccountTransaction) transaction.getTransaction()).getType();

if (type != AccountTransaction.Type.BUY && type != AccountTransaction.Type.SELL)
if (type != AccountTransaction.Type.BUY
&& type != AccountTransaction.Type.SELL
&& type != AccountTransaction.Type.COVER
&& type != AccountTransaction.Type.SHORT)
throw new IllegalArgumentException();
}
else
Expand Down Expand Up @@ -71,6 +77,20 @@ else if (tx.getType() == PortfolioTransaction.Type.SELL)

buysell.setMonetaryAmount(grossAmount.add(feesAndTaxes));
}
else if (tx.getType() == PortfolioTransaction.Type.COVER)
{
buysell.getAccountTransaction().setType(AccountTransaction.Type.SHORT);
tx.setType(PortfolioTransaction.Type.SHORT);

buysell.setMonetaryAmount(grossAmount.add(feesAndTaxes));
}
else if (tx.getType() == PortfolioTransaction.Type.SHORT)
{
buysell.getAccountTransaction().setType(AccountTransaction.Type.COVER);
tx.setType(PortfolioTransaction.Type.COVER);

buysell.setMonetaryAmount(grossAmount.add(feesAndTaxes));
}
else
{
throw new IllegalArgumentException();
Expand Down
Expand Up @@ -265,12 +265,18 @@ public void update(List<TransactionPair<?>> transactions)
createSeries(chartType, interval, transactions, yearMonths, PortfolioTransaction.Type.BUY,
Colors.ICON_BLUE);

createSeries(chartType, interval, transactions, yearMonths, PortfolioTransaction.Type.COVER,
Colors.ICON_BLUE);

createSeries(chartType, interval, transactions, yearMonths, PortfolioTransaction.Type.DELIVERY_INBOUND,
Colors.brighter(Colors.ICON_BLUE));

createSeries(chartType, interval, transactions, yearMonths, PortfolioTransaction.Type.SELL,
Colors.ICON_ORANGE);

createSeries(chartType, interval, transactions, yearMonths, PortfolioTransaction.Type.SHORT,
Colors.ICON_ORANGE);

createSeries(chartType, interval, transactions, yearMonths, PortfolioTransaction.Type.DELIVERY_OUTBOUND,
Colors.brighter(Colors.ICON_ORANGE));

Expand Down
Expand Up @@ -89,6 +89,8 @@ private void collectAccountTransactions()
{
case BUY:
case SELL:
case COVER:
case SHORT:
case TRANSFER_IN:
case TRANSFER_OUT:
accountTransactions.add(new AccountEntry(account, t));
Expand All @@ -113,6 +115,8 @@ private void collectPortfolioTransactions()
{
case BUY:
case SELL:
case SHORT:
case COVER:
case TRANSFER_IN:
case TRANSFER_OUT:
portfolioTransactions.add(new PortfolioEntry(portfolio, t));
Expand All @@ -132,7 +136,9 @@ private void matchBuySell()
AccountEntry suspect = iterAccount.next();

if (suspect.transaction.getType() != AccountTransaction.Type.BUY
&& suspect.transaction.getType() != AccountTransaction.Type.SELL)
&& suspect.transaction.getType() != AccountTransaction.Type.SELL
&& suspect.transaction.getType() != AccountTransaction.Type.COVER
&& suspect.transaction.getType() != AccountTransaction.Type.SHORT)
continue;

if (suspect.transaction.getSecurity() == null)
Expand Down