/// <summary> /// Called when trying to find something to drop (ie coming back from a caravan). This is useful even on pawns without a loadout. /// </summary> /// <param name="dropThing">Thing to be dropped from inventory.</param> /// <param name="dropCount">Amount to drop from inventory.</param> /// <returns></returns> static public bool GetAnythingForDrop(this Pawn pawn, out Thing dropThing, out int dropCount) { dropThing = null; dropCount = 0; if (pawn.inventory == null || pawn.inventory.innerContainer == null) { return(false); } Loadout loadout = pawn.GetLoadout(); if (loadout == null || loadout.Slots.NullOrEmpty()) { List <HoldRecord> recs = LoadoutManager.GetHoldRecords(pawn); if (recs != null) { // hand out any inventory item not covered by a HoldRecord. foreach (Thing thing in pawn.inventory.innerContainer) { int numContained = pawn.inventory.innerContainer.TotalStackCountOfDef(thing.def); HoldRecord rec = recs.FirstOrDefault(hr => hr.thingDef == thing.def); if (rec == null) { // we don't have a HoldRecord for this thing, drop it. dropThing = thing; dropCount = numContained > dropThing.stackCount ? dropThing.stackCount : numContained; return(true); } if (numContained > rec.count) { dropThing = thing; dropCount = numContained - rec.count; dropCount = dropCount > dropThing.stackCount ? dropThing.stackCount : dropCount; return(true); } } } else { // we have nither a HoldTracker nor a Loadout that we can ask, so just pick stuff at random from Inventory. dropThing = pawn.inventory.innerContainer.RandomElement <Thing>(); dropCount = dropThing.stackCount; } } else { // hand out an item from GetExcessThing... return(GetExcessThing(pawn, out dropThing, out dropCount)); } return(false); }
/// <summary> /// 取得持仓信息 /// </summary> public void doGetHolds() { String holdFilename = FileUtils.GetDirectory("records") + "holds.csv"; holdRecords.Clear(); if (File.Exists(holdFilename)) { new List <String>(File.ReadAllLines(holdFilename)).ForEach( x => { HoldRecord r = HoldRecord.Parse(x); if (r != null) { holdRecords.Add(r); } } ); } }
public override TradeInfo DoSell(HoldRecord holdRecord, DateTime d, Properties strategyParams, StrategyContext context) { throw new NotImplementedException(); }
/// <summary> /// Find an item that should be dropped from the pawn's inventory and how much to drop. /// </summary> /// <param name="pawn"></param> /// <param name="dropThing">The thing which should be dropped.</param> /// <param name="dropCount">The amount to drop.</param> /// <returns>bool, true indicates that the out variables are filled with something to do work on (drop).</returns> // NOTE (ProfoundDarkness): Ended up doing this by nibbling away at the pawn's inventory (or dictionary representation of ThingDefs/Count). // Probably not efficient but was easier to handle atm. static public bool GetExcessThing(this Pawn pawn, out Thing dropThing, out int dropCount) { //(ProfoundDarkness) Thanks to erdelf on the RimWorldMod discord for helping me figure out some dictionary stuff and C# concepts related to 'Primitives' (pass by Value). CompInventory inventory = pawn.TryGetComp <CompInventory>(); Loadout loadout = pawn.GetLoadout(); List <HoldRecord> records = LoadoutManager.GetHoldRecords(pawn); dropThing = null; dropCount = 0; if (inventory == null || inventory.container == null || loadout == null || loadout.Slots.NullOrEmpty()) { return(false); } Dictionary <ThingDef, int> listing = GetStorageByThingDef(pawn); // iterate over specifics and generics and Chip away at the dictionary. foreach (LoadoutSlot slot in loadout.Slots) { if (slot.thingDef != null && listing.ContainsKey(slot.thingDef)) { listing[slot.thingDef] -= slot.count; if (listing[slot.thingDef] <= 0) { listing.Remove(slot.thingDef); } } if (slot.genericDef != null) { List <ThingDef> killKeys = new List <ThingDef>(); int desiredCount = slot.count; // find dictionary entries which corespond to covered slot. foreach (ThingDef def in listing.Keys.Where(td => slot.genericDef.lambda(td))) { listing[def] -= desiredCount; if (listing[def] <= 0) { desiredCount = 0 - listing[def]; killKeys.Add(def); // the thing in inventory is exausted, forget about it. } else { break; // we have satisifed this loadout so no need to keep enumerating. } } // cleanup dictionary. foreach (ThingDef def in killKeys) { listing.Remove(def); } } } // if there is something left in the dictionary, that is what is to be dropped. // Complicated by the fact that we now consider ammo in guns as part of the inventory... if (listing.Any()) { if (records != null && !records.NullOrEmpty()) { // look at each remaining 'uneaten' thingdef in pawn's inventory. foreach (ThingDef def in listing.Keys) { HoldRecord rec = records.FirstOrDefault(r => r.thingDef == def); if (rec == null) { // the item we have extra of has no HoldRecord, drop it. dropThing = inventory.container.FirstOrDefault(t => t.def == def); if (dropThing != null) { dropCount = listing[def] > dropThing.stackCount ? dropThing.stackCount : listing[def]; return(true); } } else if (rec.count < listing[def]) { // the item we have extra of HAS a HoldRecord but the amount carried is above the limit of the HoldRecord, drop extra. dropThing = pawn.inventory.innerContainer.FirstOrDefault(t => t.def == def); if (dropThing != null) { dropCount = listing[def] - rec.count; dropCount = dropCount > dropThing.stackCount ? dropThing.stackCount : dropCount; return(true); } } } } else { foreach (ThingDef def in listing.Keys) { dropThing = inventory.container.FirstOrDefault(t => t.GetInnerIfMinified().def == def); if (dropThing != null) { dropCount = listing[def] > dropThing.stackCount ? dropThing.stackCount : listing[def]; return(true); } } } } // else return(false); }
public override TradeInfo DoSell(HoldRecord holdRecord, DateTime d, Properties strategyParam, StrategyContext context) { if (holdRecord == null) { return(null); } //取得行情库 IndicatorRepository repository = (IndicatorRepository)context.Get <Object>("repository"); if (repository == null) { return(null); } TimeSerialsDataSet ds = repository[holdRecord.code]; if (ds == null) { return(null); } KLine klineDay = ds.DayKLine; KLineItem klineItemDay = klineDay[d]; if (klineItemDay == null) { return(null); } //取得策略参数 double p_maxprofilt = strategyParam.Get <double>("maxprofilt"); int p_maxholddays = strategyParam.Get <int>("maxholddays"); double p_stoploss = strategyParam.Get <double>("stoploss"); int p_choosedays = strategyParam.Get <int>("choosedays"); double p_chooseprofilt = strategyParam.Get <double>("chooseprofilt"); GrailParameter p_grail = GrailParameter.Parse(strategyParam.Get <String>("grail")); double stampduty = context.Get <double>("stampduty"); double volumecommission = context.Get <double>("volumecommission"); //大盘要求必须卖 if (p_grail.MustSell(d, holdRecord.code)) { TradeInfo tradeInfo = new TradeInfo() { Direction = TradeDirection.Sell, Code = holdRecord.code, Amount = holdRecord.amount, EntrustPrice = klineItemDay.CLOSE, EntrustDate = d, TradeDate = d, TradePrice = klineItemDay.CLOSE, Stamps = stampduty, Fee = volumecommission, TradeMethod = TradeInfo.TM_AUTO, Reason = "大盘指数要求卖出" }; return(tradeInfo); } double profilt = (klineItemDay.CLOSE - holdRecord.buyPrice) / holdRecord.buyPrice; //判断是否到达最大收益 if (p_maxprofilt > 0) { if (profilt >= p_maxprofilt) { TradeInfo tradeInfo = new TradeInfo() { Direction = TradeDirection.Sell, Code = holdRecord.code, Amount = holdRecord.amount, EntrustPrice = klineItemDay.CLOSE, EntrustDate = d, TradeDate = d, TradePrice = klineItemDay.CLOSE, Stamps = stampduty, Fee = volumecommission, TradeMethod = TradeInfo.TM_AUTO, Reason = "盈利达到" + p_maxprofilt.ToString("F2") }; return(tradeInfo); } } //盈利超过个股预期 if (holdRecord.expect > 0) { if (profilt >= p_maxprofilt) { TradeInfo tradeInfo = new TradeInfo() { Direction = TradeDirection.Sell, Code = holdRecord.code, Amount = holdRecord.amount, EntrustPrice = klineItemDay.CLOSE, EntrustDate = d, TradeDate = d, TradePrice = klineItemDay.CLOSE, Stamps = stampduty, Fee = volumecommission, TradeMethod = TradeInfo.TM_AUTO, Reason = "盈利达到个股预期" + holdRecord.expect.ToString("F2") }; return(tradeInfo); } } //预期要求立即卖出 if (holdRecord.expect == -1) { TradeInfo tradeInfo = new TradeInfo() { Direction = TradeDirection.Sell, Code = holdRecord.code, Amount = holdRecord.amount, EntrustPrice = klineItemDay.CLOSE, EntrustDate = d, TradeDate = d, TradePrice = klineItemDay.CLOSE, Stamps = stampduty, Fee = volumecommission, TradeMethod = TradeInfo.TM_AUTO, Reason = "个股预期极低" }; return(tradeInfo); } //个股观望天数超过预期 int holdDays = CalendarUtils.WorkDayCount(holdRecord.buyDate, d); if (holdRecord.expect < 0) { if (holdDays >= holdRecord.expect * -1) { TradeInfo tradeInfo = new TradeInfo() { Direction = TradeDirection.Sell, Code = holdRecord.code, Amount = holdRecord.amount, EntrustPrice = klineItemDay.CLOSE, EntrustDate = d, TradeDate = d, TradePrice = klineItemDay.CLOSE, Stamps = stampduty, Fee = volumecommission, TradeMethod = TradeInfo.TM_AUTO, Reason = "个股预期观望超过" + (-1 * holdRecord.expect).ToString() + "天" }; return(tradeInfo); } } //达到止损线 if (p_stoploss > 0) { if (-1 * profilt > p_stoploss) { TradeInfo tradeInfo = new TradeInfo() { Direction = TradeDirection.Sell, Code = holdRecord.code, Amount = holdRecord.amount, EntrustPrice = klineItemDay.CLOSE, EntrustDate = d, TradeDate = d, TradePrice = klineItemDay.CLOSE, Stamps = stampduty, Fee = volumecommission, TradeMethod = TradeInfo.TM_AUTO, Reason = "到达止损线" + p_stoploss.ToString("F2") }; return(tradeInfo); } } //达到最大持仓天数 if (p_maxholddays > 0) { if (holdDays > p_maxholddays) { TradeInfo tradeInfo = new TradeInfo() { Direction = TradeDirection.Sell, Code = holdRecord.code, Amount = holdRecord.amount, EntrustPrice = klineItemDay.CLOSE, EntrustDate = d, TradeDate = d, TradePrice = klineItemDay.CLOSE, Stamps = stampduty, Fee = volumecommission, TradeMethod = TradeInfo.TM_AUTO, Reason = "到达最大持仓天数" + p_maxholddays.ToString() }; return(tradeInfo); } } return(null); }