@Test public void testTickerAdapter() throws IOException { // Read in the JSON from the example resources InputStream is = MtGoxAdapterTest.class.getResourceAsStream("/v0/marketdata/example-ticker-data-v0.json"); // Use Jackson to parse it ObjectMapper mapper = new ObjectMapper(); MtGoxTicker mtGoxTicker = mapper.readValue(is, MtGoxTicker.class); Ticker ticker = MtGoxAdapters.adaptTicker(mtGoxTicker, "BTC", "USD"); // System.out.println(ticker.toString()); assertThat(ticker.getLast(), is(equalTo(MoneyUtils.parse("USD 16.800000000000001")))); assertThat(ticker.getBid(), is(equalTo(MoneyUtils.parse("USD 16.79036")))); assertThat(ticker.getAsk(), is(equalTo(MoneyUtils.parse("USD 16.800000000000001")))); assertThat(ticker.getVolume(), is(equalTo(new BigDecimal("60418")))); }
/** * Adapts a BitstampTicker to a Ticker Object * * @param bitstampTicker The exchange specific ticker * @param tradableIdentifier The tradeable identifier (e.g. BTC in BTC/USD) * @param currency The currency (e.g. USD in BTC/USD) * @return The ticker */ public static Ticker adaptTicker( BitstampTicker bitstampTicker, String tradableIdentifier, String currency) { BigMoney last = MoneyUtils.parse(currency + " " + bitstampTicker.getLast()); BigMoney bid = MoneyUtils.parse(currency + " " + bitstampTicker.getBid()); BigMoney ask = MoneyUtils.parse(currency + " " + bitstampTicker.getAsk()); BigMoney high = MoneyUtils.parse(currency + " " + bitstampTicker.getHigh()); BigMoney low = MoneyUtils.parse(currency + " " + bitstampTicker.getLow()); BigDecimal volume = bitstampTicker.getVolume(); return TickerBuilder.newInstance() .withTradableIdentifier(tradableIdentifier) .withLast(last) .withBid(bid) .withAsk(ask) .withHigh(high) .withLow(low) .withVolume(volume) .build(); }
public static void main(String[] args) { Exchange bitfloor = BitfloorDemoUtils.getExchange(); PollingTradeService tradeService = bitfloor.getPollingTradeService(); printOpenOrders(tradeService); // place a limit buy order LimitOrder limitOrder = new LimitOrder( (OrderType.ASK), new BigDecimal("0.01"), "BTC", "USD", MoneyUtils.parse("USD 1250")); String limitOrderReturnValue = tradeService.placeLimitOrder(limitOrder); System.out.println("Limit Order return value: " + limitOrderReturnValue); printOpenOrders(tradeService); // Cancel the added order boolean cancelResult = tradeService.cancelOrder(limitOrderReturnValue); System.out.println("Canceling returned " + cancelResult); printOpenOrders(tradeService); }
/** * Adapt the user's trades * * @param bitstampUserTransactions * @return */ public static Trades adaptTradeHistory(BitstampUserTransaction[] bitstampUserTransactions) { List<Trade> trades = new ArrayList<Trade>(); for (int i = 0; i < bitstampUserTransactions.length; i++) { BitstampUserTransaction bitstampUserTransaction = bitstampUserTransactions[i]; if (bitstampUserTransaction .getType() .equals( BitstampUserTransaction.TransactionType .trade)) { // skip account deposits and withdrawals. OrderType orderType = bitstampUserTransaction.getUsd().doubleValue() > 0.0 ? OrderType.ASK : OrderType.BID; BigDecimal tradableAmount = bitstampUserTransaction.getBtc(); String tradableIdentifier = Currencies.BTC; String transactionCurrency = Currencies.USD; BigMoney price = MoneyUtils.parse(transactionCurrency + " " + bitstampUserTransaction.getPrice()); Date timestamp = BitstampUtils.parseDate(bitstampUserTransaction.getDatetime()); long id = bitstampUserTransaction.getId(); Trade trade = new Trade( orderType, tradableAmount, tradableIdentifier, transactionCurrency, price, timestamp, id); trades.add(trade); } } return new Trades(trades); }
/** * DTO to provide the following to the application * * <ul> * <li>Provision of persistent state * </ul> * * <p>A Item provides the central link for all the aspects that come together to describe a product * for sale. */ @Entity @Table(name = "items") public class Item implements Serializable { private static final long serialVersionUID = 38947590324750L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", nullable = false) private Long id = null; /** * The <a href="http://en.wikipedia.org/wiki/Stock-keeping_unit">stock-keeping unit</a> * * <p>Provides a mandatory code to identify an item using a local arbitrary structure, e.g. * "ABC-123". The GTIN value could be replicated here if appropriate. */ @Column(name = "sku", nullable = false) private String sku = null; /** * The <a href="http://en.wikipedia.org/wiki/Global_Trade_Item_Number">global trade item * number</a> * * <p>Provides the optional GTIN code to identify an item using international standards such as * UPC, EAN and IAN. In the case of books, ISBN is compatible with the EAN-13 standard. */ @Column(name = "gtin", nullable = true) private String gtin = null; /** Indicates if the User has been deleted (archived) */ @Column(name = "deleted", nullable = false) private boolean deleted = false; /** Provides a reason for being deleted */ @Column(name = "reasonForDelete", nullable = true) private String reasonForDelete = null; @OneToMany( targetEntity = CartItem.class, cascade = {CascadeType.ALL}, mappedBy = "primaryKey.item", fetch = FetchType.EAGER, orphanRemoval = true) private Set<CartItem> cartItems = Sets.newLinkedHashSet(); // TODO An Item has many prices depending on date, volume, discount, premium etc @Columns(columns = {@Column(name = "amount"), @Column(name = "currency")}) @Type(type = "org.multibit.mbm.db.dao.hibernate.type.BigMoneyType") private BigMoney localPrice = MoneyUtils.parseBitcoin("BTC 0.0000"); // TODO An Item has many tax rates depending on date, seller etc @Column(name = "taxRate", nullable = false) private double taxRate = 0.0; /** This collection is effectively the fields for the Item so must be eager */ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) @MapKeyEnumerated private Map<ItemField, ItemFieldDetail> itemFieldMap = Maps.newLinkedHashMap(); /* * Default constructor required for Hibernate */ public Item() {} /** * Required * * @return The internal unique ID */ public Long getId() { return id; } public void setId(Long id) { this.id = id; } /** * Required * * @return The stock-keeping unit reference (see http://en.wikipedia.org/wiki/Stock-keeping_unit) */ public String getSKU() { return sku; } public void setSKU(String sku) { this.sku = sku; } /** * Optional * * @return The global trade item number (see * http://en.wikipedia.org/wiki/Global_Trade_Item_Number) */ public String getGTIN() { return gtin; } public void setGTIN(String gtin) { this.gtin = gtin; } /** @return The tax rate applicable to this Item */ public double getTaxRate() { return taxRate; } public void setTaxRate(double taxRate) { this.taxRate = taxRate; } public boolean isDeleted() { return deleted; } public void setDeleted(boolean deleted) { this.deleted = deleted; } public String getReasonForDelete() { return reasonForDelete; } public void setReasonForDelete(String reasonForDelete) { this.reasonForDelete = reasonForDelete; } /** * The CartItem instances that bind Cart and Item<br> * Cascade occurs on the owner side * * @return Returns cartItems */ public Set<CartItem> getCartItems() { return cartItems; } public void setCartItems(Set<CartItem> cartItems) { this.cartItems = cartItems; } /** @return The price per item in the local currency */ public BigMoney getLocalPrice() { return localPrice; } public void setLocalPrice(BigMoney localPrice) { this.localPrice = localPrice; } /** @return The raw {@link ItemField} map */ public Map<ItemField, ItemFieldDetail> getItemFieldMap() { return itemFieldMap; } public void setItemFieldMap(Map<ItemField, ItemFieldDetail> itemFieldMap) { this.itemFieldMap = itemFieldMap; } /** * Utility method to assist locating default entries for a given field * * @param itemField The item field (e.g. "SUMMARY", "INSTRUCTIONS") * @return The localised content for the default locale, or null if it does not exist */ @Transient public String getItemFieldContent(ItemField itemField) { if (itemFieldMap.containsKey(itemField)) { LocalisedText localisedText = itemFieldMap.get(itemField).getPrimaryDetail(); if (localisedText != null) { return localisedText.getContent(); } } return null; } /** * Utility method to assist locating default entries for a given locale * * @param itemField The item field (e.g. "SUMMARY", "INSTRUCTIONS") * @param localeKey The locale key (e.g. "en" or "en_US") * @return The localised content for the given locale, or null if it does not exist */ @Transient public String getItemFieldContent(ItemField itemField, String localeKey) { // Get the field detail that contains the primary and secondary content ItemFieldDetail itemFieldDetail = getItemFieldDetail(itemField); if (itemFieldDetail != null) { // Attempt to locate the content for the given locale key // Always check the primary field first LocalisedText localisedText = itemFieldDetail.getPrimaryDetail(); if (localisedText != null) { if (localisedText.getLocaleKey().equalsIgnoreCase(localeKey)) { // The primary detail has a matching locale return localisedText.getContent(); } // Primary failed, so examine the secondary detail if (!itemFieldDetail.getSecondaryDetails().isEmpty()) { for (LocalisedText secondary : itemFieldDetail.getSecondaryDetails()) { if (secondary.getLocaleKey().equalsIgnoreCase(localeKey)) { // Return the first match return secondary.getContent(); } } } // No matching content in secondary } // No localised text } // Parameters are invalid return null; } /** * Utility method to assist locating particular entries * * @param itemField The item field (e.g. "SUMMARY", "INSTRUCTIONS") * @return The {@link ItemFieldDetail} providing the information, or null if none available */ @Transient public ItemFieldDetail getItemFieldDetail(ItemField itemField) { return itemFieldMap.get(itemField); } /** * Utility method to assist locating particular entries * * @param itemField The item field (e.g. "SUMMARY", "INSTRUCTIONS") * @param itemFieldDetail The contact method details providing the email address, or VOIP address * etc */ @Transient public void setItemFieldDetail(ItemField itemField, ItemFieldDetail itemFieldDetail) { itemFieldMap.put(itemField, itemFieldDetail); } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Item other = (Item) obj; return ObjectUtils.isEqual( id, other.id, sku, other.sku, gtin, other.gtin); } @Override public int hashCode() { return ObjectUtils.getHashCode(id, sku); } @Override public String toString() { return String.format("Item[id=%s, SKU='%s', GTIN='%s']]", id, sku, gtin); } }
/** * Business object to provide the following to {@link org.multibit.mbm.core.model.Item}: * * <ul> * <li>Calculation of price based on purchase order * </ul> * * <p>A price can only be determined as a result of the application of rules against and original * value. * * @since 0.0.1 */ public class PriceBuilder { private int quantity = 0; private DateTime start = DateUtils.nowUtc(); private DateTime end = DateUtils.nowUtc(); private BigMoney startingPrice = MoneyUtils.parse("GBP 0.0"); private Optional<Customer> customer = Optional.absent(); private Optional<Supplier> supplier = Optional.absent(); private List<PricingRule> pricingRules = Lists.newArrayList(); private boolean isBuilt = false; /** @return A new instance of the builder */ public static PriceBuilder newInstance() { return new PriceBuilder(); } public PriceBuilder() {} /** Handles the building process. No further configuration is possible after this. */ public BigMoney build() { validateState(); // Price is not a DTO BigMoney price = startingPrice; for (PricingRule pricingRule : pricingRules) { pricingRule.setCustomer(customer); pricingRule.setSupplier(supplier); pricingRule.setQuantity(quantity); // TODO Consider date ranges (use discriminator value e.g. R(A,B], R(o,o)) // Test filtering rules if (pricingRule.skip()) { continue; } if (pricingRule.halt()) { break; } price = pricingRule.applyTo(price); } isBuilt = true; return price; } private void validateState() { if (isBuilt) { throw new IllegalStateException("The entity has been built"); } } public PriceBuilder withPricingRule(PricingRule pricingRule) { pricingRules.add(pricingRule); return this; } /** * Add the Customer in case it affects the price (one permitted) * * @return The builder */ public PriceBuilder withCustomer(Customer customer) { this.customer = Optional.fromNullable(customer); return this; } /** * Add the Supplier in case it affects the price (one permitted) * * @return The builder */ public PriceBuilder withSupplier(Supplier supplier) { this.supplier = Optional.fromNullable(supplier); return this; } /** * @param startingPrice The starting price (default is GBP0.0) * @return The builder */ public PriceBuilder withStartingPrice(BigMoney startingPrice) { this.startingPrice = startingPrice; return this; } }