Example #1
0
  @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"))));
  }
Example #2
0
  /**
   * 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);
  }
Example #4
0
  /**
   * 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);
  }
Example #5
0
/**
 * 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;
  }
}