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

Show price deviation in portfolio open offers and history view #4845

Merged
merged 1 commit into from Nov 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ shared.amountWithCur=Amount in {0}
shared.volumeWithCur=Volume in {0}
shared.currency=Currency
shared.market=Market
shared.deviation=Deviation
shared.paymentMethod=Payment method
shared.tradeCurrency=Trade currency
shared.offerType=Offer type
Expand Down Expand Up @@ -567,6 +568,8 @@ portfolio.tab.history=History
portfolio.tab.failed=Failed
portfolio.tab.editOpenOffer=Edit offer

portfolio.closedTrades.deviation.help=Percentage price deviation from market

portfolio.pending.invalidDelayedPayoutTx=There is an issue with a missing or invalid transaction.\n\n\
Please do NOT send the fiat or altcoin payment. Contact Bisq \
developers on Keybase [HYPERLINK:https://keybase.io/team/bisq] or on the \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,18 @@

<TableView fx:id="tableView" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="tradeIdColumn" minWidth="120" maxWidth="120"/>
<TableColumn fx:id="dateColumn" minWidth="180"/>
<TableColumn fx:id="marketColumn" minWidth="100"/>
<TableColumn fx:id="tradeIdColumn" minWidth="110" maxWidth="120"/>
<TableColumn fx:id="dateColumn" minWidth="170"/>
<TableColumn fx:id="marketColumn" minWidth="75"/>
<TableColumn fx:id="priceColumn" minWidth="100"/>
<TableColumn fx:id="amountColumn" minWidth="130"/>
<TableColumn fx:id="volumeColumn" minWidth="130"/>
<TableColumn fx:id="deviationColumn" minWidth="70"/>
<TableColumn fx:id="amountColumn" minWidth="110"/>
<TableColumn fx:id="volumeColumn" minWidth="110"/>
<TableColumn fx:id="txFeeColumn" visible="false"/>
<TableColumn fx:id="tradeFeeColumn" visible="false"/>
<TableColumn fx:id="buyerSecurityDepositColumn" visible="false"/>
<TableColumn fx:id="sellerSecurityDepositColumn" visible="false"/>
<TableColumn fx:id="directionColumn" minWidth="80"/>
<TableColumn fx:id="directionColumn" minWidth="70"/>
<TableColumn fx:id="stateColumn" minWidth="80"/>
<TableColumn fx:id="avatarColumn" minWidth="40" maxWidth="40"/>
</columns>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.AutoTooltipTableColumn;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.components.InputTextField;
import bisq.desktop.components.PeerInfoIcon;
Expand Down Expand Up @@ -79,10 +80,37 @@
public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTradesViewModel> {
private final boolean useDevPrivilegeKeys;

private enum ColumnNames {
TRADE_ID(Res.get("shared.tradeId")),
DATE(Res.get("shared.dateTime")),
MARKET(Res.get("shared.market")),
PRICE(Res.get("shared.price")),
DEVIATION(Res.get("shared.deviation")),
AMOUNT(Res.get("shared.amountWithCur", Res.getBaseCurrencyCode())),
VOLUME(Res.get("shared.amount")),
TX_FEE(Res.get("shared.txFee")),
TRADE_FEE(Res.get("shared.tradeFee")),
BUYER_SEC(Res.get("shared.buyerSecurityDeposit")),
SELLER_SEC(Res.get("shared.sellerSecurityDeposit")),
OFFER_TYPE(Res.get("shared.offerType")),
STATUS(Res.get("shared.state"));

private final String text;

ColumnNames(String text) {
this.text = text;
}
@Override
public String toString() {
return text;
}
}

@FXML
TableView<ClosedTradableListItem> tableView;
@FXML
TableColumn<ClosedTradableListItem, ClosedTradableListItem> priceColumn, amountColumn, volumeColumn, txFeeColumn, tradeFeeColumn, buyerSecurityDepositColumn, sellerSecurityDepositColumn,
TableColumn<ClosedTradableListItem, ClosedTradableListItem> priceColumn, deviationColumn, amountColumn, volumeColumn,
txFeeColumn, tradeFeeColumn, buyerSecurityDepositColumn, sellerSecurityDepositColumn,
marketColumn, directionColumn, dateColumn, tradeIdColumn, stateColumn, avatarColumn;
@FXML
HBox footerBox;
Expand Down Expand Up @@ -120,18 +148,20 @@ public ClosedTradesView(ClosedTradesViewModel model,

@Override
public void initialize() {
txFeeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.txFee")));
tradeFeeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.tradeFee")));
buyerSecurityDepositColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.buyerSecurityDeposit")));
sellerSecurityDepositColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.sellerSecurityDeposit")));
priceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.price")));
amountColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", Res.getBaseCurrencyCode())));
volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amount")));
marketColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.market")));
directionColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.offerType")));
dateColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.dateTime")));
tradeIdColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.tradeId")));
stateColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.state")));
txFeeColumn.setGraphic(new AutoTooltipLabel(ColumnNames.TX_FEE.toString()));
tradeFeeColumn.setGraphic(new AutoTooltipLabel(ColumnNames.TRADE_FEE.toString()));
buyerSecurityDepositColumn.setGraphic(new AutoTooltipLabel(ColumnNames.BUYER_SEC.toString()));
sellerSecurityDepositColumn.setGraphic(new AutoTooltipLabel(ColumnNames.SELLER_SEC.toString()));
priceColumn.setGraphic(new AutoTooltipLabel(ColumnNames.PRICE.toString()));
deviationColumn.setGraphic(new AutoTooltipTableColumn<>(ColumnNames.DEVIATION.toString(),
Res.get("portfolio.closedTrades.deviation.help")).getGraphic());
amountColumn.setGraphic(new AutoTooltipLabel(ColumnNames.AMOUNT.toString()));
volumeColumn.setGraphic(new AutoTooltipLabel(ColumnNames.VOLUME.toString()));
marketColumn.setGraphic(new AutoTooltipLabel(ColumnNames.MARKET.toString()));
directionColumn.setGraphic(new AutoTooltipLabel(ColumnNames.OFFER_TYPE.toString()));
dateColumn.setGraphic(new AutoTooltipLabel(ColumnNames.DATE.toString()));
tradeIdColumn.setGraphic(new AutoTooltipLabel(ColumnNames.TRADE_ID.toString()));
stateColumn.setGraphic(new AutoTooltipLabel(ColumnNames.STATUS.toString()));
avatarColumn.setText("");

tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Expand All @@ -145,6 +175,7 @@ public void initialize() {
setBuyerSecurityDepositColumnCellFactory();
setSellerSecurityDepositColumnCellFactory();
setPriceColumnCellFactory();
setDeviationColumnCellFactory();
setVolumeColumnCellFactory();
setDateColumnCellFactory();
setMarketColumnCellFactory();
Expand All @@ -159,6 +190,9 @@ public void initialize() {
priceColumn.setComparator(nullsFirstComparing(o ->
o instanceof Trade ? ((Trade) o).getTradePrice() : o.getOffer().getPrice()
));
deviationColumn.setComparator(Comparator.comparing(o ->
o.getTradable().getOffer().isUseMarketBasedPrice() ? o.getTradable().getOffer().getMarketPriceMargin() : 1,
Comparator.nullsFirst(Comparator.naturalOrder())));
volumeColumn.setComparator(nullsFirstComparingAsTrade(Trade::getTradeVolume));
amountColumn.setComparator(nullsFirstComparingAsTrade(Trade::getTradeAmount));
avatarColumn.setComparator(nullsFirstComparingAsTrade(o ->
Expand Down Expand Up @@ -217,25 +251,27 @@ protected void activate() {
exportButton.setOnAction(event -> {
final ObservableList<TableColumn<ClosedTradableListItem, ?>> tableColumns = tableView.getColumns();
CSVEntryConverter<ClosedTradableListItem> headerConverter = transactionsListItem -> {
String[] columns = new String[12];
for (int i = 0; i < columns.length; i++)
columns[i] = ((AutoTooltipLabel) tableColumns.get(i).getGraphic()).getText();
String[] columns = new String[ColumnNames.values().length];
for (ColumnNames m : ColumnNames.values()) {
columns[m.ordinal()] = m.toString();
}
return columns;
};
CSVEntryConverter<ClosedTradableListItem> contentConverter = item -> {
String[] columns = new String[12];
columns[0] = model.getTradeId(item);
columns[1] = model.getDate(item);
columns[2] = model.getMarketLabel(item);
columns[3] = model.getPrice(item);
columns[4] = model.getAmount(item);
columns[5] = model.getVolume(item);
columns[6] = model.getTxFee(item);
columns[7] = model.getMakerFee(item);
columns[8] = model.getBuyerSecurityDeposit(item);
columns[9] = model.getSellerSecurityDeposit(item);
columns[10] = model.getDirectionLabel(item);
columns[11] = model.getState(item);
String[] columns = new String[ColumnNames.values().length];
columns[ColumnNames.TRADE_ID.ordinal()] = model.getTradeId(item);
columns[ColumnNames.DATE.ordinal()] = model.getDate(item);
columns[ColumnNames.MARKET.ordinal()] = model.getMarketLabel(item);
columns[ColumnNames.PRICE.ordinal()] = model.getPrice(item);
columns[ColumnNames.DEVIATION.ordinal()] = model.getPriceDeviation(item);
columns[ColumnNames.AMOUNT.ordinal()] = model.getAmount(item);
columns[ColumnNames.VOLUME.ordinal()] = model.getVolume(item);
columns[ColumnNames.TX_FEE.ordinal()] = model.getTxFee(item);
columns[ColumnNames.TRADE_FEE.ordinal()] = model.getMakerFee(item);
columns[ColumnNames.BUYER_SEC.ordinal()] = model.getBuyerSecurityDeposit(item);
columns[ColumnNames.SELLER_SEC.ordinal()] = model.getSellerSecurityDeposit(item);
columns[ColumnNames.OFFER_TYPE.ordinal()] = model.getDirectionLabel(item);
columns[ColumnNames.STATUS.ordinal()] = model.getState(item);
return columns;
};

Expand Down Expand Up @@ -461,6 +497,24 @@ public void updateItem(final ClosedTradableListItem item, boolean empty) {
});
}

private void setDeviationColumnCellFactory() {
deviationColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
deviationColumn.setCellFactory(
new Callback<>() {
@Override
public TableCell<ClosedTradableListItem, ClosedTradableListItem> call(
TableColumn<ClosedTradableListItem, ClosedTradableListItem> column) {
return new TableCell<>() {
@Override
public void updateItem(final ClosedTradableListItem item, boolean empty) {
super.updateItem(item, empty);
setGraphic(new AutoTooltipLabel(model.getPriceDeviation(item)));
}
};
}
});
}

private void setVolumeColumnCellFactory() {
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
volumeColumn.setCellFactory(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ String getPrice(ClosedTradableListItem item) {
return FormattingUtils.formatPrice(tradable.getOffer().getPrice());
}

String getPriceDeviation(ClosedTradableListItem item) {
if (item == null)
return "";
Tradable tradable = item.getTradable();
if (tradable.getOffer().isUseMarketBasedPrice()) {
return FormattingUtils.formatPercentagePrice(tradable.getOffer().getMarketPriceMargin());
} else {
return Res.get("shared.na");
}
}

String getVolume(ClosedTradableListItem item) {
if (item != null && item.getTradable() instanceof Trade)
return DisplayUtils.formatVolumeWithCode(((Trade) item.getTradable()).getTradeVolume());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@

<TableView fx:id="tableView" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="offerIdColumn" minWidth="110" maxWidth="130"/>
<TableColumn fx:id="dateColumn" minWidth="180"/>
<TableColumn fx:id="offerIdColumn" minWidth="110" maxWidth="120"/>
<TableColumn fx:id="dateColumn" minWidth="170"/>
<TableColumn fx:id="marketColumn" minWidth="75"/>
<TableColumn fx:id="priceColumn" minWidth="110"/>
<TableColumn fx:id="amountColumn" minWidth="100"/>
<TableColumn fx:id="volumeColumn" minWidth="150"/>
<TableColumn fx:id="priceColumn" minWidth="100"/>
<TableColumn fx:id="deviationColumn" minWidth="70"/>
<TableColumn fx:id="amountColumn" minWidth="110"/>
<TableColumn fx:id="volumeColumn" minWidth="110"/>
<TableColumn fx:id="paymentMethodColumn" minWidth="120" maxWidth="170"/>
<TableColumn fx:id="directionColumn" minWidth="80"/>
<TableColumn fx:id="directionColumn" minWidth="70"/>
<TableColumn fx:id="deactivateItemColumn" minWidth="60" maxWidth="60" sortable="false"/>
<TableColumn fx:id="editItemColumn" minWidth="50" maxWidth="60" sortable="false"/>
<TableColumn fx:id="removeItemColumn" minWidth="50" maxWidth="60" sortable="false"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.components.AutoTooltipCheckBox;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.AutoTooltipTableColumn;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.main.MainView;
import bisq.desktop.main.funds.FundsView;
Expand Down Expand Up @@ -67,7 +68,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
@FXML
TableView<OpenOfferListItem> tableView;
@FXML
TableColumn<OpenOfferListItem, OpenOfferListItem> priceColumn, amountColumn, volumeColumn,
TableColumn<OpenOfferListItem, OpenOfferListItem> priceColumn, deviationColumn, amountColumn, volumeColumn,
marketColumn, directionColumn, dateColumn, offerIdColumn, deactivateItemColumn,
removeItemColumn, editItemColumn, paymentMethodColumn;
private final Navigation navigation;
Expand All @@ -86,6 +87,8 @@ public OpenOffersView(OpenOffersViewModel model, Navigation navigation, OfferDet
public void initialize() {
paymentMethodColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.paymentMethod")));
priceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.price")));
deviationColumn.setGraphic(new AutoTooltipTableColumn<>(Res.get("shared.deviation"),
Res.get("portfolio.closedTrades.deviation.help")).getGraphic());
amountColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.BTCMinMax")));
volumeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountMinMax")));
marketColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.market")));
Expand All @@ -100,6 +103,7 @@ public void initialize() {
setDirectionColumnCellFactory();
setMarketColumnCellFactory();
setPriceColumnCellFactory();
setDeviationColumnCellFactory();
setAmountColumnCellFactory();
setVolumeColumnCellFactory();
setPaymentMethodColumnCellFactory();
Expand All @@ -116,6 +120,9 @@ public void initialize() {
marketColumn.setComparator(Comparator.comparing(model::getMarketLabel));
amountColumn.setComparator(Comparator.comparing(o -> o.getOffer().getAmount()));
priceColumn.setComparator(Comparator.comparing(o -> o.getOffer().getPrice(), Comparator.nullsFirst(Comparator.naturalOrder())));
deviationColumn.setComparator(Comparator.comparing(o ->
o.getOffer().isUseMarketBasedPrice() ? o.getOffer().getMarketPriceMargin() : 1,
Comparator.nullsFirst(Comparator.naturalOrder())));
volumeColumn.setComparator(Comparator.comparing(o -> o.getOffer().getVolume(), Comparator.nullsFirst(Comparator.naturalOrder())));
dateColumn.setComparator(Comparator.comparing(o -> o.getOffer().getDate()));
paymentMethodColumn.setComparator(Comparator.comparing(o -> o.getOffer().getPaymentMethod().getId()));
Expand Down Expand Up @@ -308,6 +315,31 @@ public void updateItem(final OpenOfferListItem item, boolean empty) {
});
}

private void setDeviationColumnCellFactory() {
deviationColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
deviationColumn.setCellFactory(
new Callback<>() {
@Override
public TableCell<OpenOfferListItem, OpenOfferListItem> call(
TableColumn<OpenOfferListItem, OpenOfferListItem> column) {
return new TableCell<>() {
@Override
public void updateItem(final OpenOfferListItem item, boolean empty) {
super.updateItem(item, empty);
getStyleClass().removeAll("offer-disabled");

if (item != null) {
if (model.isDeactivated(item)) getStyleClass().add("offer-disabled");
setGraphic(new AutoTooltipLabel(model.getPriceDeviation(item)));
} else {
setGraphic(null);
}
}
};
}
});
}

private void setVolumeColumnCellFactory() {
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
volumeColumn.setCellFactory(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,18 @@ String getPrice(OpenOfferListItem item) {
Offer offer = item.getOffer();
Price price = offer.getPrice();
if (price != null) {
String postFix = "";
if (offer.isUseMarketBasedPrice())
postFix = " (" + FormattingUtils.formatPercentagePrice(offer.getMarketPriceMargin()) + ")";
return FormattingUtils.formatPrice(price) + postFix;
return FormattingUtils.formatPrice(price);
} else {
return Res.get("shared.na");
}
}

String getPriceDeviation(OpenOfferListItem item) {
if ((item == null))
return "";
Offer offer = item.getOffer();
if (offer.isUseMarketBasedPrice()) {
return FormattingUtils.formatPercentagePrice(offer.getMarketPriceMargin());
} else {
return Res.get("shared.na");
}
Expand Down