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); }
/// <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); }
/// <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)); }
public TradePointInfo(AppTypes.TradeActions action, int dataIdx) { this.TradeAction = action; this.DataIdx = dataIdx; }
public TradePointInfo(AppTypes.TradeActions action, int dataIdx, BusinessInfo info) { this.TradeAction = action; this.DataIdx = dataIdx; this.BusinessInfo.Set(info); }
//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; } }
public void Add(AppTypes.TradeActions action, int idx) { this.Add(new TradePointInfo(action, idx)); }
public void Add(AppTypes.TradeActions action, int idx, BusinessInfo info) { this.Add(new TradePointInfo(action, idx, info)); }
/// <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); } }
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); }