Beispiel #1
0
        public static data.baseDS.transactionsDataTable MakeTransaction(AppTypes.TradeActions type, string stockCode,
                                                                        string portfolioCode, int qty, decimal feePerc)
        {
            string errorText = "";

            data.baseDS.transactionsDataTable retVal = myClient.MakeTransaction(out errorText, type, stockCode, portfolioCode, qty, feePerc);
            if (retVal == null)
            {
                common.system.ShowErrorMessage(errorText);
            }
            return(retVal);
        }
Beispiel #2
0
        /// <summary>
        ///  Create records to keep stock transaction (buy,sell...)
        ///  - transactions
        ///  - investorStock
        /// </summary>
        /// <param name="onDate"></param>
        /// <param name="type"></param>
        /// <param name="stockCode"></param>
        /// <param name="portfolio"></param>
        /// <param name="qty"></param>
        /// <param name="amt"></param>
        public static databases.baseDS.transactionsDataTable MakeTransaction(AppTypes.TradeActions type, string stockCode, string portfolioCode, int qty, decimal feePerc, out string errorText)
        {
            errorText = "";
            databases.baseDS.stockExchangeRow marketRow = databases.DbAccess.GetStockExchange(stockCode);
            if (marketRow == null)
            {
                return(null);
            }

            errorText = "";
            DateTime onTime = DateTime.Now;

            //Price
            databases.baseDS.priceDataRow priceRow = databases.DbAccess.GetLastPriceData(stockCode);
            if (priceRow == null)
            {
                errorText = Languages.Libs.GetString("cannotDoTransaction");
                return(null);
            }
            decimal amt    = qty * priceRow.closePrice * marketRow.priceRatio;
            decimal feeAmt = (decimal)Math.Round(feePerc * amt / 100, common.system.GetPrecisionFromMask(Settings.sysMaskLocalAmt));

            databases.baseDS.portfolioRow portfolioRow = databases.DbAccess.GetPortfolio(portfolioCode);
            if (portfolioRow == null)
            {
                errorText = String.Format(Languages.Libs.GetString("dataNotFound"), "[portfolio]");
                return(null);
            }
            switch (type)
            {
            case AppTypes.TradeActions.Buy:
            case AppTypes.TradeActions.Accumulate:
                portfolioRow.usedCapAmt += amt;
                portfolioRow.usedCapAmt += feeAmt;
                break;

            default:     //Sell
                portfolioRow.usedCapAmt -= amt;
                portfolioRow.usedCapAmt += feeAmt;
                break;
            }
            if (portfolioRow.startCapAmt - portfolioRow.usedCapAmt < 0)
            {
                portfolioRow.CancelEdit();
                errorText = String.Format(Languages.Libs.GetString("outOfMoney"), portfolioRow.startCapAmt - portfolioRow.usedCapAmt - amt - feeAmt);
                return(null);
            }

            //Create records to store data
            databases.baseDS.transactionsDataTable  transTbl         = new databases.baseDS.transactionsDataTable();
            databases.baseDS.investorStockDataTable investorStockTbl = new databases.baseDS.investorStockDataTable();
            databases.baseDS.transactionsRow        transRow;
            databases.baseDS.investorStockRow       stockRow;

            transRow = transTbl.NewtransactionsRow();
            databases.AppLibs.InitData(transRow);
            transRow.onTime    = onTime;
            transRow.tranType  = (byte)type;
            transRow.stockCode = stockCode;
            transRow.portfolio = portfolioCode;
            transRow.qty       = qty;
            transRow.amt       = amt;
            transRow.feeAmt    = feeAmt;
            transRow.status    = (byte)AppTypes.CommonStatus.Close;
            transTbl.AddtransactionsRow(transRow);

            //Update stock
            DateTime onDate = onTime.Date;

            switch (type)
            {
            case AppTypes.TradeActions.Buy:
            case AppTypes.TradeActions.Accumulate:
                investorStockTbl.Clear();
                databases.DbAccess.LoadData(investorStockTbl, stockCode, portfolioCode, onDate);
                if (investorStockTbl.Count == 0)
                {
                    stockRow = investorStockTbl.NewinvestorStockRow();
                    databases.AppLibs.InitData(stockRow);
                    stockRow.buyDate   = onDate;
                    stockRow.stockCode = stockCode;
                    stockRow.portfolio = portfolioCode;
                    investorStockTbl.AddinvestorStockRow(stockRow);
                }
                stockRow      = investorStockTbl[0];
                stockRow.qty += qty; stockRow.buyAmt += amt;
                break;

            default:     //Sell
                DateTime applicableDate = onDate.AddDays(-marketRow.minBuySellDay);
                investorStockTbl.Clear();
                databases.DbAccess.LoadData(investorStockTbl, stockCode, portfolioCode);
                decimal remainQty = qty;
                for (int idx = 0; idx < investorStockTbl.Count; idx++)
                {
                    if (investorStockTbl[idx].buyDate > applicableDate)
                    {
                        continue;
                    }
                    if (investorStockTbl[idx].qty >= remainQty)
                    {
                        investorStockTbl[idx].buyAmt = (investorStockTbl[idx].qty - remainQty) * (investorStockTbl[idx].qty == 0 ? 0 : investorStockTbl[idx].buyAmt / investorStockTbl[idx].qty);
                        investorStockTbl[idx].qty    = (investorStockTbl[idx].qty - remainQty);
                        remainQty = 0;
                    }
                    else
                    {
                        remainQty -= investorStockTbl[idx].qty;
                        investorStockTbl[idx].buyAmt = 0;
                        investorStockTbl[idx].qty    = 0;
                    }
                    if (remainQty == 0)
                    {
                        break;
                    }
                }
                if (remainQty > 0)
                {
                    errorText = String.Format(Languages.Libs.GetString("outOfQty"), qty - remainQty);
                    return(null);
                }
                break;
            }
            //Delete empty stock
            for (int idx = 0; idx < investorStockTbl.Count; idx++)
            {
                if (investorStockTbl[idx].qty != 0)
                {
                    continue;
                }
                investorStockTbl[idx].Delete();
            }

            //Update data with transaction support
            TransactionScopeOption tranOption;

            tranOption = (commonClass.SysLibs.sysUseTransactionInUpdate ? TransactionScopeOption.Required : TransactionScopeOption.Suppress);
            using (TransactionScope scope = new TransactionScope(tranOption))
            {
                databases.DbAccess.UpdateData(portfolioRow);
                databases.DbAccess.UpdateData(investorStockTbl);
                databases.DbAccess.UpdateData(transTbl);
                scope.Complete();
            }
            return(transTbl);
        }
Beispiel #3
0
 /// <summary>
 ///  Create records to keep stock transaction (buy,sell...)
 ///  - transactions
 ///  - investorStock
 /// </summary>
 /// <param name="onDate"></param>
 /// <param name="type"></param>
 /// <param name="stockCode"></param>
 /// <param name="portfolio"></param>
 /// <param name="qty"></param>
 /// <param name="amt"></param>
 ///
 public data.baseDS.transactionsDataTable MakeTransaction(AppTypes.TradeActions type, string stockCode, string portfolioCode, int qty, decimal feePerc, out string errorText)
 {
     return(application.AppLibs.MakeTransaction(type, stockCode, portfolioCode, qty, feePerc, out errorText));
 }
Beispiel #4
0
 public TradePointInfo(AppTypes.TradeActions action, int dataIdx)
 {
     this.TradeAction = action;
     this.DataIdx     = dataIdx;
 }
Beispiel #5
0
 public TradePointInfo(AppTypes.TradeActions action, int dataIdx, BusinessInfo info)
 {
     this.TradeAction = action;
     this.DataIdx     = dataIdx;
     this.BusinessInfo.Set(info);
 }
Beispiel #6
0
        //Swicth language. Note that the order of items must be preserved
        public static void SetLanguage(ComboBox.ObjectCollection items, Type type)
        {
            StringCollection saveKeys = new StringCollection();

            for (int idx = 0; idx < items.Count; idx++)
            {
                common.myComboBoxItem item = (common.myComboBoxItem)items[idx];
                saveKeys.Add(item.Value);
            }
            if (type == typeof(AppTypes.TimeScale))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindTimeScaleByCode(saveKeys[idx]);
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.TimeScale item = (AppTypes.TimeScale)obj;
                    items.Add(new common.myComboBoxItem(item.Description, item.Code));
                }
                return;
            }

            if (type == typeof(AppTypes.TradeActions))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindCodeInEnum(saveKeys[idx], typeof(AppTypes.TradeActions));
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.TradeActions item = (AppTypes.TradeActions)obj;
                    items.Add(new common.myComboBoxItem(AppTypes.Type2Text(item), item.ToString()));
                }
                return;
            }


            if (type == typeof(AppTypes.TimeRanges))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindCodeInEnum(saveKeys[idx], typeof(AppTypes.TimeRanges));
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.TimeRanges item = (AppTypes.TimeRanges)obj;
                    items.Add(new common.myComboBoxItem(AppTypes.Type2Text(item), item.ToString()));
                }
                return;
            }
            if (type == typeof(AppTypes.StrategyTypes))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindCodeInEnum(saveKeys[idx], typeof(AppTypes.StrategyTypes));
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.StrategyTypes item = (AppTypes.StrategyTypes)obj;
                    items.Add(new common.myComboBoxItem(AppTypes.Type2Text(item), item.ToString()));
                }
                return;
            }
            if (type == typeof(AppTypes.Sex))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindCodeInEnum(saveKeys[idx], typeof(AppTypes.Sex));
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.Sex item = (AppTypes.Sex)obj;
                    items.Add(new common.myComboBoxItem(AppTypes.Type2Text(item), item.ToString()));
                }
                return;
            }
            if (type == typeof(AppTypes.CommonStatus))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindCodeInEnum(saveKeys[idx], typeof(AppTypes.CommonStatus));
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.CommonStatus item = (AppTypes.CommonStatus)obj;
                    items.Add(new common.myComboBoxItem(AppTypes.Type2Text(item), item.ToString()));
                }
                return;
            }
            if (type == typeof(AppTypes.ChartTypes))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindCodeInEnum(saveKeys[idx], typeof(AppTypes.ChartTypes));
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.ChartTypes item = (AppTypes.ChartTypes)obj;
                    items.Add(new common.myComboBoxItem(AppTypes.Type2Text(item), item.ToString()));
                }
                return;
            }
            if (type == typeof(AppTypes.BizSectorTypes))
            {
                items.Clear();
                for (int idx = 0; idx < saveKeys.Count; idx++)
                {
                    object obj = FindCodeInEnum(saveKeys[idx], typeof(AppTypes.BizSectorTypes));
                    if (obj == null)
                    {
                        continue;
                    }
                    AppTypes.BizSectorTypes item = (AppTypes.BizSectorTypes)obj;
                    items.Add(new common.myComboBoxItem(AppTypes.Type2Text(item), item.ToString()));
                }
                return;
            }
        }
Beispiel #7
0
 public void Add(AppTypes.TradeActions action, int idx)
 {
     this.Add(new TradePointInfo(action, idx));
 }
Beispiel #8
0
 public void Add(AppTypes.TradeActions action, int idx, BusinessInfo info)
 {
     this.Add(new TradePointInfo(action, idx, info));
 }
Beispiel #9
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);
            }
        }
Beispiel #10
0
        public static databases.baseDS.tradeAlertDataTable MakeAlertSummary(databases.baseDS.tradeAlertDataTable tbl)
        {
            SummaryItem buyCount, sellCount;

            databases.baseDS.tradeAlertRow       sumRow;
            databases.baseDS.tradeAlertDataTable sumTbl = new databases.baseDS.tradeAlertDataTable();
            sumTbl.DefaultView.Sort = sumTbl.onTimeColumn.ColumnName + "," + sumTbl.stockCodeColumn.ColumnName;
            DataRowView[]         foundRows;
            common.DictionaryList buyCountList  = new common.DictionaryList();
            common.DictionaryList sellCountList = new common.DictionaryList();

            object obj;

            //Sum
            for (int idx = 0; idx < tbl.Count; idx++)
            {
                foundRows = sumTbl.DefaultView.FindRows(new object[] { tbl[idx].onTime.Date, tbl[idx].stockCode });
                if (foundRows.Length != 0)
                {
                    sumRow = (databases.baseDS.tradeAlertRow)foundRows[0].Row;
                }
                else
                {
                    sumRow = sumTbl.NewtradeAlertRow();
                    databases.AppLibs.InitData(sumRow);
                    sumRow.onTime    = tbl[idx].onTime.Date;
                    sumRow.stockCode = tbl[idx].stockCode;
                    sumTbl.AddtradeAlertRow(sumRow);
                }
                AppTypes.TradeActions action = (AppTypes.TradeActions)tbl[idx].tradeAction;
                switch (action)
                {
                case AppTypes.TradeActions.Buy:
                case AppTypes.TradeActions.Accumulate:
                    obj = buyCountList.Find(sumRow.onTime.ToString() + sumRow.stockCode);
                    if (obj == null)
                    {
                        buyCount = new SummaryItem(sumRow.stockCode, sumRow.onTime);
                    }
                    else
                    {
                        buyCount = (SummaryItem)obj;
                    }
                    buyCount.Qty++;
                    buyCountList.Add(sumRow.onTime.ToString() + sumRow.stockCode, buyCount);
                    break;

                case AppTypes.TradeActions.Sell:
                case AppTypes.TradeActions.ClearAll:
                    obj = sellCountList.Find(sumRow.onTime.ToString() + sumRow.stockCode);
                    if (obj == null)
                    {
                        sellCount = new SummaryItem(sumRow.stockCode, sumRow.onTime);
                    }
                    else
                    {
                        sellCount = (SummaryItem)obj;
                    }
                    sellCount.Qty++;
                    sellCountList.Add(sumRow.onTime.Date.ToString() + sumRow.stockCode, sellCount);
                    break;
                }
            }
            //Make summary message
            for (int idx = 0; idx < sumTbl.Count; idx++)
            {
                sumTbl[idx].msg = "";
                obj             = buyCountList.Find(sumTbl[idx].onTime.ToString() + sumTbl[idx].stockCode);
                if (obj != null)
                {
                    sumTbl[idx].msg += (sumTbl[idx].msg.Trim() != "" ? " , " : "") + (obj as SummaryItem).Qty.ToString() + " " + Languages.Libs.GetString("buyAlert");
                }

                obj = sellCountList.Find(sumTbl[idx].onTime.ToString() + sumTbl[idx].stockCode);
                if (obj != null)
                {
                    sumTbl[idx].msg += (sumTbl[idx].msg.Trim() != "" ? " , " : "") + (obj as SummaryItem).Qty.ToString() + " " + Languages.Libs.GetString("sellAlert");
                }
            }
            return(sumTbl);
        }