示例#1
0
        /// <summary>
        /// Estimate the profit from advices produced by analysis process.
        /// The function will produce a list of "transactions" assuming to be done from analysis advices.
        /// </summary>
        /// <param name="data"> Data used for analysis </param>
        /// <param name="tradePoints">Trade point list generated by analysis process</param>
        /// <param name="options">User- specific options : captital, max Buy...</param>
        /// <param name="returnObj">Returned object </param>
        /// <param name="afterEachEstimationFunc">Call-back function at the end of each tradepoind estimation</param>
        /// <param name="afterEstimationFunc">Call-back function at the end of estimation process</param>
        ///
        public static void EstimateTrading(AnalysisData data, TradePointInfo[] tradePoints, EstimateOptions options,
                                           object returnObj, AfterEachEstimationFunc afterEachEstimationFunc, AfterEstimationFunc afterEstimationFunc)
        {
            EstimationData myEstimationData = new EstimationData();

            global::data.baseDS.stockExchangeRow marketRow = application.AppLibs.GetStockExchange(data.DataStockCode);
            decimal initCapAmt       = options.TotalCapAmt * options.MaxBuyAmtPerc / 100;
            decimal priceWeight      = marketRow.priceRatio;
            decimal feePerc          = marketRow.tranFeePerc / 100;
            short   buy2SellInterval = marketRow.minBuySellDay;

            data.baseDS.stockCodeRow stockCodeRow = application.SysLibs.FindAndCache_StockCode(data.DataStockCode);
            if (stockCodeRow == null)
            {
                return;
            }

            int     adviceDataIdx, lastBuyId = -1;
            decimal stockQty = 0, qty;
            decimal maxBuyQty = (decimal)(stockCodeRow.noOutstandingStock * options.MaxBuyQtyPerc / 100);
            decimal stockAmt = 0, stockPrice = 0, amt, feeAmt, totalFeeAmt = 0;
            decimal cashAmt = initCapAmt;

            DateTime transDate = common.Consts.constNullDate;;

            for (int idx = 0; idx < tradePoints.Length; idx++)
            {
                adviceDataIdx            = tradePoints[idx].DataIdx;
                qty                      = 0; amt = 0;
                myEstimationData.ignored = false;
                AppTypes.TradeActions action = tradePoints[idx].TradeAction;

                stockPrice = (decimal)data.Close[adviceDataIdx];
                transDate  = DateTime.FromOADate(data.DateTime[adviceDataIdx]);
                switch (action)
                {
                case AppTypes.TradeActions.Buy:
                    //Assume that we can only buy if we have money
                    qty = (stockPrice == 0 ? 0 : Math.Floor(cashAmt / ((stockPrice * priceWeight) * (1 + feePerc))));
                    if (qty > maxBuyQty)
                    {
                        qty = maxBuyQty;
                    }
                    if (qty != 0)
                    {
                        amt          = qty * stockPrice * priceWeight;
                        stockAmt    += amt;
                        stockQty    += qty;
                        feeAmt       = Math.Round(amt * feePerc, 0);
                        cashAmt     -= amt + feeAmt;
                        totalFeeAmt += feeAmt;
                        lastBuyId    = adviceDataIdx;
                    }
                    else
                    {
                        myEstimationData.ignored = true;
                    }
                    break;

                case AppTypes.TradeActions.Sell:
                    //Can sell if own some stock
                    if (stockQty <= 0)
                    {
                        myEstimationData.ignored = true;
                        break;
                    }
                    // Not applicable to sell
                    if (lastBuyId < 0)
                    {
                        myEstimationData.ignored = true;
                        break;
                    }

                    // T+4 contrainst ?
                    if (common.dateTimeLibs.DateDiffInDays(DateTime.FromOADate(data.DateTime[lastBuyId]).Date,
                                                           DateTime.FromOADate(data.DateTime[adviceDataIdx]).Date) < buy2SellInterval)
                    {
                        // Keep inapplicable Sells ??
                        if (commonClass.Settings.sysKeepInApplicableSell)
                        {
                            int      transDataIdx     = -1;
                            DateTime minAllowSellDate = DateTime.FromOADate(data.DateTime[lastBuyId]).Date.AddDays(buy2SellInterval);
                            //If it is the last trade point, find the next applicable date
                            if (idx >= tradePoints.Length - 1)
                            {
                                transDataIdx = FindDateIdx(data, tradePoints[idx].DataIdx + 1, data.DateTime.Count - 1, minAllowSellDate);
                            }
                            else
                            {
                                //If the next trade point is before or at [minAllowSellDate], ignore this
                                if (DateTime.FromOADate(data.DateTime.Values[tradePoints[idx + 1].DataIdx]).Date <= minAllowSellDate)
                                {
                                    myEstimationData.ignored = true;
                                }
                                else
                                {
                                    //Find the next applicable date after this point and before next point
                                    transDataIdx = FindDateIdx(data, tradePoints[idx].DataIdx + 1, tradePoints[idx + 1].DataIdx - 1, minAllowSellDate);
                                }
                            }
                            if (transDataIdx < 0)
                            {
                                myEstimationData.ignored = true;
                            }
                            else
                            {
                                stockPrice = (decimal)data.Close[transDataIdx];
                                transDate  = DateTime.FromOADate(data.DateTime[transDataIdx]).Date;
                            }
                        }
                        else
                        {
                            myEstimationData.ignored = true;
                        }
                    }
                    //Ok, sell it
                    if (!myEstimationData.ignored)
                    {
                        qty          = stockQty;
                        amt          = qty * stockPrice * priceWeight;
                        stockQty     = 0; stockAmt = 0;
                        feeAmt       = Math.Round(amt * feePerc, 0);
                        cashAmt     += amt - feeAmt;
                        totalFeeAmt += feeAmt;
                    }
                    break;
                }
                myEstimationData.tradeAction = action.ToString();
                myEstimationData.onDate      = transDate;
                myEstimationData.price       = stockPrice;
                myEstimationData.qty         = qty;
                myEstimationData.amt         = amt;
                myEstimationData.feeAmt      = totalFeeAmt;
                myEstimationData.ownedQty    = stockQty;
                myEstimationData.ownedAmt    = stockAmt;
                myEstimationData.cashAmt     = cashAmt;
                myEstimationData.profitAmt   = cashAmt + stockAmt - initCapAmt;
                if (afterEachEstimationFunc != null)
                {
                    afterEachEstimationFunc(myEstimationData, returnObj);
                }
            }
            if (afterEstimationFunc != null)
            {
                afterEstimationFunc(myEstimationData, returnObj);
            }
        }
示例#2
0
        /// <summary>
        /// Estimate the profit from advices produced by analysis process.
        /// The function will produce a list of "transactions" assuming to be done from analysis advices.
        /// </summary>
        /// <param name="data"> Data used for analysis </param>
        /// <param name="tradePoints">Trade point list generated by analysis process</param>
        /// <param name="options">User- specific options : captital, max Buy...</param>
        /// <param name="returnObj">Returned object </param>
        /// <param name="afterEachEstimationFunc">Call-back function at the end of each tradepoind estimation</param>
        /// <param name="afterEstimationFunc">Call-back function at the end of estimation process</param>
        ///
        public static void EstimateTrading(AnalysisData data, TradePointInfo[] tradePoints, EstimateOptions options,
                                           object returnObj, AfterEachEstimationFunc afterEachEstimationFunc, AfterEstimationFunc afterEstimationFunc)
        {
            EstimationData myEstimationData = new EstimationData();

            global::databases.baseDS.stockExchangeRow marketRow = databases.DbAccess.GetStockExchange(data.DataStockCode);
            decimal initCapAmt       = options.TotalCapAmt * options.MaxBuyAmtPerc / 100;
            decimal priceWeight      = marketRow.priceRatio;
            decimal feePerc          = marketRow.tranFeePerc / 100;
            short   buy2SellInterval = marketRow.minBuySellDay;

            databases.baseDS.stockCodeRow stockCodeRow = application.SysLibs.FindAndCache_StockCode(data.DataStockCode);
            if (stockCodeRow == null)
            {
                return;
            }

            int     transDataIdx, lastBuyId = -1;
            decimal stockQty = 0, qty;
            decimal maxBuyQty = (decimal)(stockCodeRow.noOutstandingStock * options.MaxBuyQtyPerc / 100);
            decimal stockAmt = 0, stockPrice = 0, amt, feeAmt, totalFeeAmt = 0;
            decimal cashAmt = initCapAmt;


            //DateTime transDate = common.Consts.constNullDate; ;
            for (int idx = 0; idx < tradePoints.Length; idx++)
            {
                transDataIdx             = tradePoints[idx].DataIdx;
                qty                      = 0; amt = 0;
                myEstimationData.ignored = false;

                stockPrice = (decimal)data.Close[transDataIdx];
                switch (tradePoints[idx].TradeAction)
                {
                case AppTypes.TradeActions.Buy:
                    //Assume that we can only buy if we have money
                    qty = (stockPrice == 0 ? 0 : Math.Floor(cashAmt / ((stockPrice * priceWeight) * (1 + feePerc))));
                    if (qty > maxBuyQty)
                    {
                        qty = maxBuyQty;
                    }
                    if (qty != 0)
                    {
                        amt          = qty * stockPrice * priceWeight;
                        stockAmt    += amt;
                        stockQty    += qty;
                        feeAmt       = Math.Round(amt * feePerc, 0);
                        cashAmt     -= amt + feeAmt;
                        totalFeeAmt += feeAmt;
                        lastBuyId    = transDataIdx;
                    }
                    else
                    {
                        myEstimationData.ignored = true;
                    }
                    break;

                case AppTypes.TradeActions.Sell:
                    //Can sell if own some stock
                    if (stockQty <= 0)
                    {
                        myEstimationData.ignored = true;
                        break;
                    }
                    // Not applicable to sell
                    if (lastBuyId < 0)
                    {
                        myEstimationData.ignored = true;
                        break;
                    }
                    //==========================
                    // Check T+4 contrainst
                    //==========================
                    int minAllowSellPointIdx = lastBuyId + buy2SellInterval;

                    // [minAllowSellPoint] is out of data bound , ignore it.
                    if (minAllowSellPointIdx >= data.DateTime.Count)
                    {
                        myEstimationData.ignored = true;
                    }

                    // Violate T4 contrainst ?
                    if (!myEstimationData.ignored && tradePoints[idx].DataIdx < minAllowSellPointIdx)
                    {
                        // Keep inapplicable Sells ??
                        if (Settings.sysKeepInApplicableSell)
                        {
                            //If it is the last trade point, make transaction (sell) at [minAllowSellPoint]
                            if (idx >= tradePoints.Length - 1)
                            {
                                transDataIdx = minAllowSellPointIdx;
                            }
                            else
                            {
                                //If there is some trade point between it and [minAllowSellPoint], ignore it
                                if (tradePoints[idx + 1].DataIdx < minAllowSellPointIdx)
                                {
                                    myEstimationData.ignored = true;
                                }
                                else
                                {
                                    transDataIdx = minAllowSellPointIdx;
                                }
                            }
                        }
                        else
                        {
                            myEstimationData.ignored = true;
                        }
                    }
                    //Ok, sell it
                    if (myEstimationData.ignored != true)
                    {
                        stockPrice   = (decimal)data.Close[transDataIdx];
                        qty          = stockQty;
                        amt          = qty * stockPrice * priceWeight;
                        stockQty     = 0; stockAmt = 0;
                        feeAmt       = Math.Round(amt * feePerc, 0);
                        cashAmt     += amt - feeAmt;
                        totalFeeAmt += feeAmt;

                        //Adjust trade point to refresh chages by T4 constrainst
                        tradePoints[idx].DataIdx = transDataIdx;
                    }
                    else
                    {
                        tradePoints[idx].isValid = false;
                    }
                    break;
                }
                myEstimationData.tradeAction = tradePoints[idx].TradeAction;
                myEstimationData.onDate      = DateTime.FromOADate(data.DateTime[transDataIdx]);
                myEstimationData.price       = stockPrice;
                myEstimationData.qty         = qty;
                myEstimationData.amt         = amt;
                myEstimationData.feeAmt      = totalFeeAmt;
                myEstimationData.ownedQty    = stockQty;
                myEstimationData.ownedAmt    = stockAmt;
                myEstimationData.cashAmt     = cashAmt;
                myEstimationData.profitAmt   = cashAmt + stockAmt - initCapAmt;
                if (afterEachEstimationFunc != null)
                {
                    afterEachEstimationFunc(myEstimationData, returnObj);
                }
            }
            if (afterEstimationFunc != null)
            {
                afterEstimationFunc(myEstimationData, returnObj);
            }
        }