com.icoin.trading.tradeengine.query.tradeexecuted.repositories.TradeExecutedQueryRepositoryImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.icoin.trading.tradeengine.query.tradeexecuted.repositories.TradeExecutedQueryRepositoryImpl.java

Source

/*
 * Copyright (c) 2010-2012. Axon Framework
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.icoin.trading.tradeengine.query.tradeexecuted.repositories;

import com.google.common.collect.Lists;
import com.icoin.trading.tradeengine.domain.model.order.OrderStatus;
import com.icoin.trading.tradeengine.query.order.OrderEntry;
import com.icoin.trading.tradeengine.query.order.OrderType;
import com.icoin.trading.tradeengine.query.order.PriceAggregate;
import com.icoin.trading.tradeengine.query.tradeexecuted.OpenHighLowCloseVolume;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.CommandResult;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.Fields;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

import static com.homhon.util.Asserts.hasLength;
import static com.homhon.util.Asserts.isTrue;
import static com.homhon.util.Asserts.notNull;
import static org.springframework.data.domain.Sort.Direction.DESC;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.group;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.limit;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.previousOperation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.sort;
import static org.springframework.data.mongodb.core.query.Criteria.where;

/**
 * @author Jettro Coenradie
 */
public class TradeExecutedQueryRepositoryImpl implements TradeExecutedQueryRepositoryCustom {

    private static final String TRADE_EXECUTED_ENTRY_COLLECTION = "tradeExecutedEntry";
    private static Logger logger = LoggerFactory.getLogger(TradeExecutedQueryRepositoryImpl.class);

    private MongoTemplate mongoTemplate;

    @Resource(name = "trade.mongoTemplate")
    public void setMongoTemplate(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @Override
    public List<OpenHighLowCloseVolume> ohlc(String orderBookIdentifier, Date start, Date end, Pageable pageable) {
        hasLength(orderBookIdentifier);
        notNull(pageable);

        DBObject command = BasicDBObjectBuilder.start("aggregate", TRADE_EXECUTED_ENTRY_COLLECTION).get();

        final DBObject criteriaObject = Criteria.where("orderBookIdentifier").is(orderBookIdentifier)
                .and("tradeTime").gte(start).lt(end).getCriteriaObject();
        DBObject match = BasicDBObjectBuilder.start("$match", criteriaObject).get();

        DBObject projection = BasicDBObjectBuilder
                .start("year", BasicDBObjectBuilder.start("$year", "$tradeTime").get())
                .append("month", BasicDBObjectBuilder.start("$month", "$tradeTime").get())
                .append("day", BasicDBObjectBuilder.start("$dayOfMonth", "$tradeTime").get())
                .append("hour", BasicDBObjectBuilder.start("$hour", "$tradeTime").get())
                .append("minute", BasicDBObjectBuilder.start("$minute", "$tradeTime").get())
                .append("tradedPrice", 1).append("tradedAmount", 1).append("_id", 0).get();

        DBObject project = BasicDBObjectBuilder.start("$project", projection).get();

        //{ "aggregate" : "tradeExecutedEntry" ,
        // "pipeline" : [ { "$match" : { "orderBookIdentifier" : "f830f7e3-9f99-4688-92e7-6dbafc7220a8" ,
        // "tradeTime" : { "$gte" : { "$date" : "2007-12-12T04:12:12.120Z"} ,
        // "$lt" : { "$date" : "2012-12-12T04:12:04.120Z"}}}} ,
        // { "$project" : { "tradeTime" : 1 , "tradedPrice.amount" : 1 , "tradedAmount.amount" : 1 , "year" :
        // { "$year" : [ "$tradeTime"]} , "month" : { "$month" : [ "$tradeTime"]} , "week" : { "$week" : [ "$tradeTime"]}}} ,
        // { "$group" : { "_id" : "$year" , "open" : { "$first" : "$tradedPrice"} , "high" : { "$max" : "$tradedPrice"} ,
        // "low" : { "$min" : "$tradedPrice"} , "close" : { "$last" : "$tradedPrice"} , "volume" : { "$sum" : "$tradedAmount"}}} ,
        // { "$skip" : 0} , { "$limit" : 100}]}

        //        {"$project": {
        //            "year":       {"$year": "$dt"},
        //            "month":      {"$month": "$dt"},
        //            "day":        {"$dayOfMonth": "$dt"},
        //            "hour":       {"$hour": "$dt"},
        //            "minute":     {"$minute": "$dt"},
        //            "second":     {"$second": "$dt"},
        //            "dt": 1,
        //                    "p": 1 }},
        //        {"_id" : {"year": "$year", "month": "$month", "day": "$day", "hour": "$hour", "minute": "$minute" },
        //            "open":  {"$first": "$p"},
        //            "high":  {"$max": "$p"},
        //            "low":   {"$min": "$p"},
        //            "close": {"$last": "$p"} }} ] )

        //        02:41:22.649 [main] DEBUG c.i.t.t.q.t.r.TradeExecutedQueryRepositoryImpl - aggregation { "aggregate" : "tradeExecutedEntry" , "pipeline" : [ { "$match" : { "orderBookIdentifier" : "c623022b-9baa-437a-a70f-b59adead3ecf" , "tradeTime" : { "$gte" : { "$date" : "2007-12-12T04:12:12.120Z"} , "$lt" : { "$date" : "2012-12-12T04:12:04.120Z"}}}} , { "$project" : { "year" : { "$year" : "$tradeTime"} , "month" : { "$month" : "$tradeTime"} , "day" : { "$dayOfMonth" : "$tradeTime"} , "hour" : { "$hour" : "$tradeTime"} , "minute" : { "$minute" : "$tradeTime"} , "tradedPrice" : 1 , "tradedAmount" : 1 , "_id" : 0}} , { "$group" : { "_id" : { "year" : "$year" , "priceCcy" : "$tradedPrice.currency" , "amountCcy" : "$tradedAmount.currency"} , "open" : { "$first" : "$tradedPrice.amount"} , "high" : { "$max" : "$tradedPrice.amount"} , "low" : { "$min" : "$tradedPrice.amount"} , "close" : { "$last" : "$tradedPrice.amount"} , "volume" : { "$sum" : "$tradedAmount.amount"}}}]} found :[ { "_id" : { "year" : 2012 , "priceCcy" : "CNY" , "amountCcy" : "BTC"} , "open" : 10500 , "high" : 10500 , "low" : 10500 , "close" : 10500 , "volume" : 11550000000} , { "_id" : { "year" : 2010 , "priceCcy" : "CNY" , "amountCcy" : "BTC"} , "open" : 10500 , "high" : 10500 , "low" : 10500 , "close" : 10500 , "volume" : 2100000000} , { "_id" : { "year" : 2011 , "priceCcy" : "CNY" , "amountCcy" : "BTC"} , "open" : 10500 , "high" : 10500 , "low" : 10500 , "close" : 10500 , "volume" : 1050000000}]
        //        02:46:45.023 [main] DEBUG c.i.t.t.q.t.r.TradeExecutedQueryRepositoryImpl - aggregation { "aggregate" : "tradeExecutedEntry" , "pipeline" : [ { "$match" : { "orderBookIdentifier" : "04527652-b53b-47bf-967d-2001fbe18c13" , "tradeTime" : { "$gte" : { "$date" : "2007-12-12T04:12:12.120Z"} , "$lt" : { "$date" : "2012-12-12T04:12:04.120Z"}}}} , { "$project" : { "year" : { "$year" : "$tradeTime"} , "month" : { "$month" : "$tradeTime"} , "day" : { "$dayOfMonth" : "$tradeTime"} , "hour" : { "$hour" : "$tradeTime"} , "minute" : { "$minute" : "$tradeTime"} , "tradedPrice" : 1 , "tradedAmount" : 1 , "_id" : 0}} , { "$group" : { "_id" : { "year" : "$year" , "priceCcy" : "$tradedPrice.currency" , "amountCcy" : "$tradedAmount.currency"} , "open" : { "$first" : "$tradedPrice.amount"} , "high" : { "$max" : "$tradedPrice.amount"} , "low" : { "$min" : "$tradedPrice.amount"} , "close" : { "$last" : "$tradedPrice.amount"} , "volume" : { "$sum" : "$tradedAmount.amount"}}}]} found :[ { "_id" : { "year" : 2012 , "priceCcy" : "CNY" , "amountCcy" : "BTC"} , "open" : 10500 , "high" : 10500 , "low" : 10500 , "close" : 10500 , "volume" : 11550000000} , { "_id" : { "year" : 2010 , "priceCcy" : "CNY" , "amountCcy" : "BTC"} , "open" : 10500 , "high" : 10500 , "low" : 10500 , "close" : 10500 , "volume" : 2100000000} , { "_id" : { "year" : 2011 , "priceCcy" : "CNY" , "amountCcy" : "BTC"} , "open" : 10500 , "high" : 10500 , "low" : 10500 , "close" : 10500 , "volume" : 1050000000}]

        final DBObject groupId = BasicDBObjectBuilder.start("year", "$year")
                //                .append("month", "$month")
                //                .append("day", "$dayOfMonth")
                //                .append("hour", "$hour")
                //                .append("minute", "$minute")
                .append("priceCcy", "$tradedPrice.currency").append("amountCcy", "$tradedAmount.currency").get();
        DBObject groupOp = BasicDBObjectBuilder.start("_id", groupId)
                .append("open", BasicDBObjectBuilder.start("$first", "$tradedPrice.amount").get())
                .append("high", BasicDBObjectBuilder.start("$max", "$tradedPrice.amount").get())
                .append("low", BasicDBObjectBuilder.start("$min", "$tradedPrice.amount").get())
                .append("close", BasicDBObjectBuilder.start("$last", "$tradedPrice.amount").get())
                .append("volume", BasicDBObjectBuilder.start("$sum", "$tradedAmount.amount").get()).get();

        DBObject group = BasicDBObjectBuilder.start("$group", groupOp).get();

        final BasicDBList pipeline = new BasicDBList();
        pipeline.add(match);
        pipeline.add(project);
        pipeline.add(group);
        command.put("pipeline", pipeline);

        CommandResult commandResult = mongoTemplate.executeCommand(command);
        handleCommandError(commandResult, command);

        // map results
        @SuppressWarnings("unchecked")
        Iterable<DBObject> resultSet = (Iterable<DBObject>) commandResult.get("result");
        List<OpenHighLowCloseVolume> mappedResults = Lists.newLinkedList();

        if (logger.isDebugEnabled()) {
            logger.debug("aggregation {} found :{}", command, resultSet);
        }

        System.err.println(Long.MAX_VALUE / 100000000);
        return null;
    }

    /**
     * Inspects the given {@link CommandResult} for erros and potentially throws an
     * {@link org.springframework.dao.InvalidDataAccessApiUsageException} for that error.
     *
     * @param result must not be {@literal null}.
     * @param source must not be {@literal null}.
     */
    private void handleCommandError(CommandResult result, DBObject source) {

        try {
            result.throwOnError();
        } catch (MongoException ex) {

            String error = result.getErrorMessage();
            error = error == null ? "NO MESSAGE" : error;

            throw new InvalidDataAccessApiUsageException(
                    "Command execution failed:  Error [" + error + "], Command = " + source, ex);
        }
    }

    //    //    @Override
    //    public List<OpenHighLowCloseVolume> ohlc0(String orderBookIdentifier, Date start, Date end, Pageable pageable) {
    //        hasLength(orderBookIdentifier);
    //        notNull(pageable);
    //
    ////        db.mycollection.aggregate([
    ////                {"$match": {"dt": {"$lt" : end_dt, "$gte" : start_dt  }}},
    ////        {"$project": {
    ////            "year":       {"$year": "$dt"},
    ////            "month":      {"$month": "$dt"},
    ////            "day":        {"$dayOfMonth": "$dt"},
    ////            "hour":       {"$hour": "$dt"},
    ////            "minute":     {"$minute": "$dt"},
    ////            "second":     {"$second": "$dt"},
    ////            "dt": 1,
    ////                    "p": 1 }},
    ////        {"$sort": {"dt": 1}},
    ////        {"$group":
    ////            {"_id" : {"year": "$year", "month": "$month", "day": "$day", "hour": "$hour", "minute": "$minute" },
    ////                "open":  {"$first": "$p"},
    ////                "high":  {"$max": "$p"},
    ////                "low":   {"$min": "$p"},
    ////                "close": {"$last": "$p"} }} ] )
    //
    //        //order is: match, order, sort, limit
    //        final ProjectionOperation project = project(
    //                Fields.from(Fields.field("tradeTime"),
    //                        Fields.field("tradedPrice.amount", "tradedPrice"),
    //                        Fields.field("tradedAmount.amount", "tradeAmount")
    ////                        Fields.field("priceCurrency", "tradedPrice.currency"),
    ////                Fields.field("tradeCurrency", "tradedAmount.currency"))
    //                ));
    //
    //        //{ "aggregate" : "tradeExecutedEntry" ,
    //        // "pipeline" : [ { "$match" : { "orderBookIdentifier" : "f830f7e3-9f99-4688-92e7-6dbafc7220a8" ,
    //        // "tradeTime" : { "$gte" : { "$date" : "2007-12-12T04:12:12.120Z"} ,
    //        // "$lt" : { "$date" : "2012-12-12T04:12:04.120Z"}}}} ,
    //        // { "$project" : { "tradeTime" : 1 , "tradedPrice.amount" : 1 , "tradedAmount.amount" : 1 , "year" :
    //        // { "$year" : [ "$tradeTime"]} , "month" : { "$month" : [ "$tradeTime"]} , "week" : { "$week" : [ "$tradeTime"]}}} ,
    //        // { "$group" : { "_id" : "$year" , "open" : { "$first" : "$tradedPrice"} , "high" : { "$max" : "$tradedPrice"} ,
    //        // "low" : { "$min" : "$tradedPrice"} , "close" : { "$last" : "$tradedPrice"} , "volume" : { "$sum" : "$tradedAmount"}}} ,
    //        // { "$skip" : 0} , { "$limit" : 100}]}
    //
    //        //        { "aggregate" : "tradeExecutedEntry" ,
    //        // "pipeline" : [ { "$match" : { "orderBookIdentifier" : "4ed97c9a-d391-477a-bbdc-cbe4c41865d9" ,
    //        // "tradeTime" : { "$gte" : { "$date" : "2007-12-12T04:12:12.120Z"} ,
    //        // "$lt" : { "$date" : "2012-12-12T04:12:04.120Z"}}}} ,
    //        // { "$project" : { "tradeTime" : 1 , "tradedPrice.amount" : "$tradedPrice" , "tradedAmount.amount" : "$tradeAmount" , "year" : { "$year" : [ "$tradeTime"]} , "month" : { "$month" : [ "$tradeTime"]} , "week" : { "$week" : [ "$tradeTime"]}}} , { "$group" : { "_id" : "$year" , "open" : { "$first" : "$tradedPrice"} , "high" : { "$max" : "$tradedPrice"} , "low" : { "$min" : "$tradedPrice"} , "close" : { "$last" : "$tradedPrice"} , "volume" : { "$sum" : "$tradeAmount"}}} , { "$skip" : 0} , { "$limit" : 100}]}
    //
    //        System.out.println(project.getFields());
    //        Aggregation aggregation = newAggregation(TradeExecutedEntry.class,
    //                match(where("orderBookIdentifier").is(orderBookIdentifier)
    //                        .and("tradeTime").gte(start).lt(end)),
    ////                project("tradeTime", "tradedPrice.amount", "tradedPrice.currency","tradedAmount.amount","tradedAmount.currency")
    //                project
    ////                        .and("tradedAmount.amount").as("tradedAmount")
    ////                        .and("tradedPrice.amount").as("tradedPrice")
    ////                        .and("tradedAmount").nested(bind("amount", "tradedAmount"))
    ////                        .and("tradedAmount.amount").as("tradedA")
    //                        .andExpression("year(tradeTime)").as("year") //
    //                        .andExpression("month(tradeTime)").as("month") //
    //                        .andExpression("week(tradeTime)").as("week") //
    ////                        .and("tradeTime").project("hour").as("hour")
    ////                .and("tradeTime").project("minute").as("minute")
    ////                .and("tradeTime").project("second").as("second")
    //                ,
    ////                group(Fields.from(Fields.field("year", "year"))),
    ////                sort(DESC, "tradeTime", "tradedAmount.amount"),
    ////                project()
    ////                .and("year").as("year")
    ////                        ,
    //                group("year")
    //                        .first("tradedPrice").as("open")
    //                        .max("tradedPrice").as("high")
    //                        .min("tradedPrice").as("low")
    //                        .last("tradedPrice").as("close")
    //                        .sum("tradeAmount").as("volume"),
    ////                group(Fields.fields("year"))
    ////                        /*.and(Fields.field("amountCurrency")*///)
    //////                        .and(Fields.field("year", "year"))
    //////                        .and(Fields.field("month", "month"))
    //////                        .and(Fields.field("day", "day"))
    //////                        .and(Fields.field("hour", "hour"))
    //////                )
    ////                        .first("tradedPrice").as("open")
    ////                        .max("tradedPrice").as("high")
    ////                        .min("tradedPrice").as("low")
    ////                        .last("tradedPrice").as("close")
    ////                        .sum("tradedAmount.amount").as("volume"),
    //                skip(pageable.getOffset()),
    //                limit(pageable.getPageSize())
    //        );
    //
    //
    //        AggregationResults<DBObject> result = mongoTemplate.aggregate(aggregation, "tradeExecutedEntry", DBObject.class);
    //
    //        List<DBObject> openHighLowCloseVolumes = result.getMappedResults();
    //
    //        if (logger.isDebugEnabled()) {
    //            logger.debug("aggregation {} found :{}", aggregation, openHighLowCloseVolumes);
    //        }
    //        return null;
    //    }

    //    /**
    //     * Applies the given {@link Pageable} to the given {@link MongodbQuery}.
    //     *
    //     * @param query
    //     * @param pageable
    //     * @return
    //     */
    //    private MongodbQuery<T> applyPagination(MongodbQuery<T> query, Pageable pageable) {
    //
    //        if (pageable == null) {
    //            return query;
    //        }
    //
    //        query = query.offset(pageable.getOffset()).limit(pageable.getPageSize());
    //        return applySorting(query, pageable.getSort());
    //    }
    //
    //    /**
    //     * Applies the given {@link org.springframework.data.domain.Sort} to the given {@link MongodbQuery}.
    //     *
    //     * @param query
    //     * @param sort
    //     * @return
    //     */
    //    private MongodbQuery<T> applySorting(MongodbQuery<T> query, Sort sort) {
    //
    //        if (sort == null) {
    //            return query;
    //        }
    //
    //        for (Sort.Order order : sort) {
    //            query.orderBy(toOrder(order));
    //        }
    //
    //        return query;
    //    }

    public List<PriceAggregate> findOrderAggregatedPrice(String orderBookIdentifier, OrderType type, Date toDate,
            int limit) {
        isTrue(limit >= 1);
        //order is: match, order, sort, limit
        TypedAggregation<OrderEntry> aggregation = newAggregation(OrderEntry.class,
                match(where("orderStatus").is(OrderStatus.PENDING.toString()).and("type").is(type.toString())
                        .and("itemRemaining.amount").gt(0).and("placedDate").lte(toDate).and("orderBookIdentifier")
                        .is(orderBookIdentifier)),
                group(Fields.from(Fields.field("price", "itemPrice.amount"))
                        .and(Fields.field("priceCurrency", "itemPrice.currency"))
                        .and(Fields.field("amountCurrency", "itemRemaining.currency"))).sum("itemRemaining.amount")
                                .as("sumUpAmountPerPrice"),
                sort(DESC, previousOperation()), limit(limit));

        AggregationResults<PriceAggregate> result = mongoTemplate.aggregate(aggregation, PriceAggregate.class);

        List<PriceAggregate> priceAggregateList = result.getMappedResults();

        if (logger.isDebugEnabled()) {
            logger.debug("aggregation {} found :{}", aggregation, priceAggregateList);
        }
        return priceAggregateList;
    }
}