public static string Serialize(OffsetInfo oi) { string m = string.Format("{0},{1},{2},{3},{4},{5}", oi.ProfitDist, oi.StopDist, oi.ProfitPercent, oi.StopPercent, oi.NormalizeSize, oi.MinimumLotSize); return(m); }
public void CustomOffsets() { // get default offset ot.DefaultOffset = SampleOffset(); // verify that random symbol has default values Assert.AreEqual(ot.DefaultOffset.ProfitPercent, ot[SYMB].ProfitPercent); Assert.AreEqual(ot.DefaultOffset.StopPercent, ot[SYMB].StopPercent); Assert.AreEqual(ot.DefaultOffset.ProfitDist, ot[SYMB].ProfitDist); Assert.AreEqual(ot.DefaultOffset.StopDist, ot[SYMB].StopDist); // add custom offset different than default ot[SYMB] = new OffsetInfo(POFFSET * 2, SOFFSET * 2, .5m, .5m,true,100); // verify custom has taken effect Assert.AreEqual(ot.DefaultOffset.ProfitPercent/2, ot[SYMB].ProfitPercent); Assert.AreEqual(ot.DefaultOffset.StopPercent/2, ot[SYMB].StopPercent); Assert.AreEqual(ot.DefaultOffset.ProfitDist*2, ot[SYMB].ProfitDist); Assert.AreEqual(ot.DefaultOffset.StopDist*2, ot[SYMB].StopDist); // verify another symbol still has default Assert.AreEqual(ot.DefaultOffset.ProfitPercent, ot[SYMC].ProfitPercent); Assert.AreEqual(ot.DefaultOffset.StopPercent, ot[SYMC].StopPercent); Assert.AreEqual(ot.DefaultOffset.ProfitDist, ot[SYMC].ProfitDist); Assert.AreEqual(ot.DefaultOffset.StopDist, ot[SYMC].StopDist); }
/// <summary> /// this must be called once per position tracker, for each position update. /// if you are using your own position tracker with this trailing stop(eg from offset tracker, or somewhere else) /// you only need to adjust it once, so if you adjust it directly you don't need to call again here. /// </summary> /// <param name="fill"></param> public void Adjust(Trade fill) { // get index for symbol int idx = symidx(fill.symbol); // only do following if we're tracking trail for this symbol if (idx != NOSYM) { // get current position size int psize = _pt[fill.symbol].UnsignedSize; // get trailing information OffsetInfo trail = _trail[idx]; // get expected position size int esize = psize - Calc.Norm2Min(psize * trail.StopPercent, trail.MinimumLotSize); // get actual position size after change int asize = psize - fill.UnsignedSize; // if expected and actual match, mark pending as false if (esize == asize) { D("filled trailing stop for: " + fill.symbol); _pendingfill[idx] = false; } } _pt.Adjust(fill); // if we're flat now, make sure ref price is reset if (_pt[fill.symbol].isFlat) { _ref[idx] = 0; } }
public static string Serialize(OffsetInfo oi) { string m = string.Format("{0},{1},{2},{3},{4},{5}", oi.ProfitDist, oi.StopDist, oi.ProfitPercent, oi.StopPercent, oi.NormalizeSize, oi.MinimumLotSize); return m; }
public void SerializeDeserialize() { OffsetInfo oi = new OffsetInfo(2, 1); string msg = OffsetInfo.Serialize(oi); OffsetInfo co = OffsetInfo.Deserialize(msg); Assert.AreEqual(2,oi.ProfitDist); Assert.AreEqual(1, oi.StopDist); }
void doupdate(string sym, bool poschange) { // is update ignored? if (IgnoreUpdate(sym)) { return; } // get our offset values OffsetInfo off = GetOffset(sym); // see if we have profit if (off.hasProfit) { // cancel existing profits cancel(off.ProfitId); // wait a moment to allow cancel to be received System.Threading.Thread.Sleep(_cancelpause); } // see if we have stop if (off.hasStop) { // cancel existing stops cancel(off.StopId); // wait a moment to allow cancel to be received System.Threading.Thread.Sleep(_cancelpause); } if (!off.hasProfit) { // get new profit Order profit = Calc.PositionProfit(_pt[sym], off.ProfitDist, off.ProfitPercent, off.NormalizeSize, off.MinimumLotSize); // if it's valid, send and track it if (profit.isValid) { profit.id = Ids.AssignId; off.ProfitId = profit.id; SendOffset(profit); } } if (!off.hasStop) { // get new stop Order stop = Calc.PositionStop(_pt[sym], off.StopDist, off.StopPercent, off.NormalizeSize, off.MinimumLotSize); // if it's valid, send and track if (stop.isValid) { stop.id = Ids.AssignId; off.StopId = stop.id; SendOffset(stop); } } // make sure new offset info is reflected SetOffset(sym, off); }
void SetOffset(string sym, OffsetInfo off) { OffsetInfo v; if (_offvals.TryGetValue(sym, out v)) { _offvals[sym] = off; } else { _offvals.Add(sym, off); } }
public void ResendTest2() { // reset "book" to start from scratch reset(); // SETOFFSET("IBM", 0.03, 0, 1, 0); const string sym = "IBM"; const decimal pdist = .03m; const decimal pct = 1; ot[sym] = new OffsetInfo(pdist, 0, pct, 0, false, 1); Assert.AreEqual(pdist, ot[sym].ProfitDist); Assert.AreEqual(pct, ot[sym].ProfitPercent); // entry fill // 094508: fill: 20100423,94532,IBM,SELL,10,128.85, 0 fill(new TradeImpl(sym, 128.85m, -10)); Assert.AreEqual(-10, ot.PositionTracker[sym].Size); // profit // 094508: sent new profit: 634076112353906253 BUY10 [email protected] [] 634076112353906253 Assert.AreEqual(1, profits.Count); Order profit = profits[0]; Assert.AreEqual(128.82m, profit.price); Assert.AreEqual(10, profit.size); // fill profit // 094609: fill: 20100423,94632,IBM,BUY,10,128.82, 634076112353906253 // 094609: IBM hit profit: 634076112353906253 Assert.IsTrue(profit.Fill(TickImpl.NewTrade(sym, 128.82m, 10))); Trade profitfill = (Trade)profit; fill(profitfill); // we're now flat // 094609: IBM now flat. Assert.IsTrue(ot.PositionTracker[sym].isFlat); // tick ot.newTick(TickImpl.NewTrade(sym,128.82m,100)); Assert.AreEqual(0, profits.Count); // re-enter //094722: fill: 20100423,94746,IBM,SELL,10,128.86, 100947 fill(new TradeImpl(sym, 128.86m, -10)); Assert.AreEqual(-10, ot.PositionTracker[sym].Size); // we should now have a profit offset Assert.AreEqual(1, profits.Count); profit = profits[0]; Assert.AreEqual(128.83m, profit.price); Assert.AreEqual(10, profit.size); }
/// <summary> /// this must be called once per position tracker, for each position update. /// if you are using your own position tracker with this trailing stop(eg from offset tracker, or somewhere else) /// you MUST call TrailTrackers Adjust and NOT call your position tracker's adjust /// </summary> /// <param name="fill"></param> public void Adjust(Trade fill) { // get index for symbol int idx = symidx(fill.symbol); // only do following if we're tracking trail for this symbol if (idx != NOSYM) { // get current position size int psize = _pt[fill.symbol].UnsignedSize; // get trailing information OffsetInfo trail = _trail[idx]; // get actual position size after change int asize = psize - fill.UnsignedSize; // if expected and actual match, mark pending as false if (esize[idx] == asize) { D(fill.symbol + " trailing stop completely filled with: " + fill.ToString()); _pendingfill[idx] = false; } else { v(fill.symbol + " trail partial fill: " + fill.ToString() + " e: " + esize[idx] + " != a: " + asize); } } else { v(fill.symbol + " fill: " + fill.ToString() + " ignored while trail disabled."); } _pt.Adjust(fill); // if we're flat now, make sure ref price is reset if (_pt[fill.symbol].isFlat) { _ref[idx] = 0; v(fill.symbol + " flat, reset trail reference price."); } }
/// <summary> /// get a stop order for a position given offset information /// </summary> /// <param name="p"></param> /// <param name="offset"></param> /// <returns></returns> public static Order PositionStop(Position p, OffsetInfo offset) { return PositionStop(p, offset.StopDist, offset.StopPercent, offset.NormalizeSize,offset.MinimumLotSize); }
/// <summary> /// get profit order for given position given offset information /// </summary> /// <param name="p"></param> /// <param name="offset"></param> /// <returns></returns> public static Order PositionProfit(Position p, OffsetInfo offset) { return PositionProfit(p, offset.ProfitDist, offset.ProfitPercent,offset.NormalizeSize,offset.MinimumLotSize); }
/// <summary> /// copy an existing offset to this one /// </summary> /// <param name="copy"></param> public OffsetInfo(OffsetInfo copy) : this(copy.ProfitDist, copy.StopDist, copy.ProfitPercent, copy.StopPercent, copy.NormalizeSize, copy.MinimumLotSize) { }
void SetOffset(string sym, OffsetInfo off) { OffsetInfo v; if (_offvals.TryGetValue(sym, out v)) _offvals[sym] = off; else _offvals.Add(sym, off); }
void cancel(OffsetInfo offset) { cancel(offset.ProfitId); cancel(offset.StopId); }
public void TrailStartedAfterFirePoint() { // setup trail tracker TrailTracker tt = new TrailTracker(); tt.isValid = true; const string acct = "DEFAULT"; tt.pt.DefaultAccount = acct; tt.SendOrder += new OrderDelegate(tt_SendOrder); //tt.SendDebug += new DebugFullDelegate(tt_SendDebug); // set 15c trailing stop tt.DefaultTrail = new OffsetInfo(0, .15m); // verify it's set Assert.AreEqual(.15m, tt.DefaultTrail.StopDist); // tt.TrailByDefault = true; // put in a position to track tt.Adjust(new PositionImpl(SYM, 11.00m, 100, 0m,acct)); // check position in tt-pt Assert.AreEqual(1, tt.pt.Count); // manually enter a trail tt[SYM] = new OffsetInfo(0m, .25m); // check if trail entered for symbol Assert.AreEqual(.25m, tt[SYM].StopDist); // get feed Tick[] tape = SampleData(); // test broker Broker b = new Broker(); // get fills over to trail tracker b.GotFill += new FillDelegate(tt.Adjust); // get orders from trail tracker tt.SendOrder += new OrderDelegate(b.SendOrder); // no orders to start oc = 0; // iterate through feed for (int i = 0; i < tape.Length; i++) { Tick k = tape[i]; // set a date and time k.date = 20070926; k.time = 95500; // execute orders, nothing to do on first two ticks b.Execute(k); // pass every tick to tracker tt.newTick(k); } Assert.AreEqual(1, oc); }
/// <summary> /// pass arbitrary price to use for trail reference price /// </summary> /// <param name="symbol"></param> /// <param name="p"></param> public void newPoint(string symbol, decimal p) { // get index for symbol int idx = symidx(symbol); // setup parameters OffsetInfo trail = null; decimal refp = 0; // see if we trail this symbol if ((idx == NOSYM) && _trailbydefault) { // get parameters idx = _trail.Count; refp = p; trail = new OffsetInfo(_defaulttrail); // save them _symidx.Add(symbol, idx); _ref.Add(refp); _pendingfill.Add(false); // just in case user is modifying on seperate thread lock (_trail) { _trail.Add(trail); } D("trail tracking: " + symbol + " " + trail.ToString()); } else if ((idx == NOSYM) && !_trailbydefault) return; else { // get parameters refp = _ref[idx]; // in case tracker started after trail stop should have been broken. if (refp == 0 && _pt[symbol].isValid) { refp = _pt[symbol].AvgPrice; } // just in case user tries to modify on seperate thread lock (_trail) { trail = _trail[idx]; } } // see if we need to update ref price if ((refp == 0) || (_pt[symbol].isLong && (refp < p)) || (_pt[symbol].isShort && (refp > p))) { // update refp = p; // save it _ref[idx] = refp; } // see if we broke our trail if (!_pendingfill[idx] && (trail.StopDist!=0) && (Math.Abs(refp - p) > trail.StopDist)) { // notify D("hit trailing stop at: " + p.ToString("F2")); // mark pending order _pendingfill[idx] = true; // get order Order flat = new MarketOrderFlat(_pt[symbol], trail.StopPercent, trail.NormalizeSize, trail.MinimumLotSize); // get order id flat.id = _id.AssignId; // send flat order SendOrder(flat); // notify D("enforcing trail with: " + flat.ToString()); if (HitOffset != null) HitOffset(symbol, flat.id,p); } }
public static Order PositionStop(Position p, OffsetInfo offset) { return(PositionStop(p, offset.ProfitDist, offset.ProfitPercent)); }
/// <summary> /// must pass ticks as received to this function, in order to have trailing stops executed at proper time. /// </summary> /// <param name="k"></param> public void GotTick(Tick k) { // see if we're turned on if (!isValid) return; // see if we can exit when trail is broken if (SendOrder == null) return; // see if we have anything to trail against if (_pt[k.symbol].isFlat) return; // only care about trades if (!k.isTrade) return; // get index for symbol int idx = symidx(k.symbol); // setup parameters OffsetInfo trail = null; decimal refp = 0; // see if we trail this symbol if ((idx == NOSYM) && _trailbydefault) { // get parameters idx = _trail.Count; refp = k.trade; trail = new OffsetInfo(_defaulttrail); // save them _symidx.Add(k.symbol, idx); _ref.Add(refp); // just in case user is modifying on seperate thread lock (_trail) { _trail.Add(trail); } } else if ((idx == NOSYM) && !_trailbydefault) return; else { // get parameters refp = _ref[idx]; // just in case user tries to modify on seperate thread lock (_trail) { trail = _trail[idx]; } } // see if we need to update ref price if ((refp == 0) || (_pt[k.symbol].isLong && (refp < k.trade)) || (_pt[k.symbol].isShort && (refp > k.trade))) { // update refp = k.trade; // save it _ref[idx] = refp; } // see if we broke our trail if (Math.Abs(refp - k.trade) > trail.StopDist) { // send flat order SendOrder(new MarketOrderFlat(_pt[k.symbol], trail.StopPercent, trail.NormalizeSize, trail.MinimumLotSize)); } }
/// <summary> /// must pass ticks as received to this function, in order to have trailing stops executed at proper time. /// </summary> /// <param name="k"></param> public void GotTick(Tick k) { // see if we're turned on if (!isValid) { return; } // see if we can exit when trail is broken if (SendOrder == null) { return; } // see if we have anything to trail against if (_pt[k.symbol].isFlat) { return; } // only care about trades if (!k.isTrade) { return; } // get index for symbol int idx = symidx(k.symbol); // setup parameters OffsetInfo trail = null; decimal refp = 0; // see if we trail this symbol if ((idx == NOSYM) && _trailbydefault) { // get parameters idx = _trail.Count; refp = k.trade; trail = new OffsetInfo(_defaulttrail); // save them _symidx.Add(k.symbol, idx); _ref.Add(refp); _pendingfill.Add(false); // just in case user is modifying on seperate thread lock (_trail) { _trail.Add(trail); } D("trail tracking: " + k.symbol + " " + trail.ToString()); } else if ((idx == NOSYM) && !_trailbydefault) { return; } else { // get parameters refp = _ref[idx]; // just in case user tries to modify on seperate thread lock (_trail) { trail = _trail[idx]; } } // see if we need to update ref price if ((refp == 0) || (_pt[k.symbol].isLong && (refp < k.trade)) || (_pt[k.symbol].isShort && (refp > k.trade))) { // update refp = k.trade; // save it _ref[idx] = refp; } // see if we broke our trail if (!_pendingfill[idx] && (trail.StopDist != 0) && (Math.Abs(refp - k.trade) > trail.StopDist)) { // notify D("hit trailing stop at: " + k.trade.ToString("n2")); // mark pending order _pendingfill[idx] = true; // get order Order flat = new MarketOrderFlat(_pt[k.symbol], trail.StopPercent, trail.NormalizeSize, trail.MinimumLotSize); // get order id flat.id = _id.AssignId; // send flat order SendOrder(flat); // notify D("enforcing trail with: " + flat.ToString()); } }
/// <summary> /// pass arbitrary price to use for trail reference price /// </summary> /// <param name="symbol"></param> /// <param name="p"></param> public void newPoint(string symbol, decimal p) { // get index for symbol int idx = symidx(symbol); // setup parameters OffsetInfo trail = null; decimal refp = 0; // see if we trail this symbol if ((idx == NOSYM) && _trailbydefault) { // get parameters idx = _trail.Count; refp = p; trail = new OffsetInfo(_defaulttrail); // save them _symidx.Add(symbol, idx); _ref.Add(refp); _pendingfill.Add(false); // just in case user is modifying on seperate thread lock (_trail) { _trail.Add(trail); } D("trail tracking: " + symbol + " " + trail.ToString()); } else if ((idx == NOSYM) && !_trailbydefault) { return; } else { // get parameters refp = _ref[idx]; // in case tracker started after trail stop should have been broken. if (refp == 0 && _pt[symbol].isValid) { refp = _pt[symbol].AvgPrice; } // just in case user tries to modify on seperate thread lock (_trail) { trail = _trail[idx]; } } // see if we need to update ref price if ((refp == 0) || (_pt[symbol].isLong && (refp < p)) || (_pt[symbol].isShort && (refp > p))) { // update refp = p; // save it _ref[idx] = refp; } // see if we broke our trail if (!_pendingfill[idx] && (trail.StopDist != 0) && (Math.Abs(refp - p) > trail.StopDist)) { // notify D("hit trailing stop at: " + p.ToString("F2")); // mark pending order _pendingfill[idx] = true; // get order Order flat = new MarketOrderFlat(_pt[symbol], trail.StopPercent, trail.NormalizeSize, trail.MinimumLotSize); // get order id flat.id = _id.AssignId; // send flat order SendOrder(flat); // notify D("enforcing trail with: " + flat.ToString()); if (HitOffset != null) { HitOffset(symbol, flat.id, p); } } }
/// <summary> /// pass arbitrary price to use for trail reference price /// </summary> /// <param name="symbol"></param> /// <param name="p"></param> public void newPoint(string symbol, decimal p) { // get index for symbol int idx = symidx(symbol); // setup parameters OffsetInfo trail = null; decimal refp = 0; // see if we trail this symbol if ((idx == NOSYM) && _trailbydefault) { // get parameters idx = _trail.Count; refp = p; trail = new OffsetInfo(_defaulttrail); // save them _symidx.Add(symbol, idx); _ref.Add(refp); _pendingfill.Add(false); firecount.addindex(symbol, 0); esize.addindex(symbol,pt[symbol].UnsignedSize); // just in case user is modifying on seperate thread lock (_trail) { _trail.Add(trail); } D(symbol+" trail tracking modified: "+trail.ToString()); } else if ((idx == NOSYM) && !_trailbydefault) { return; } else { // get parameters refp = _ref[idx]; // in case tracker started after trail stop should have been broken. if (refp == 0 && _pt[symbol].isValid) { refp = _pt[symbol].AvgPrice; } // just in case user tries to modify on seperate thread lock (_trail) { trail = _trail[idx]; } } // see if we need to update ref price if ((refp == 0) || (_pt[symbol].isLong && (refp < p)) || (_pt[symbol].isShort && (refp > p))) { // update refp = p; // save it _ref[idx] = refp; // notify v(symbol + " new reference price: " + p); } // see if we broke our trail var testdist = Math.Abs(refp - p); var trailtest = testdist> trail.StopDist; if (!_pendingfill[idx] && (trail.StopDist!=0) && trailtest && (MaxFireCount>firecount[idx])) { // notify D(symbol+" hit trailing stop at: " + p.ToString("F2")); // mark pending order _pendingfill[idx] = true; // get order Order flat = new MarketOrderFlat(_pt[symbol], trail.StopPercent, trail.NormalizeSize, trail.MinimumLotSize); // get order id flat.id = _id.AssignId; // adjust expectation esize[idx] -= flat.UnsignedSize; // count fire firecount[idx]++; // send flat order SendOrder(flat); // notify D(symbol+" enforcing trail with: " + flat.ToString()+" esize: "+esize[idx]+" count: "+firecount[idx]); if (HitOffset != null) HitOffset(symbol, flat.id,p); } else if (!_noverb) { if (_pendingfill[idx]) v(symbol + " waiting for trail fill."); else if (trail.StopDist == 0) v(symbol + " trail has been disabled."); else if (!trailtest) { v(symbol + " trail not hit, current dist: " + testdist + " trailamt: " + trail.StopDist); } else if (MaxFireCount > firecount[idx]) { v(symbol + " trail max fire reached at: " + firecount[idx] + " max: " + MaxFireCount); } } }
/// <summary> /// pass arbitrary price to use for trail reference price /// </summary> /// <param name="symbol"></param> /// <param name="p"></param> public void newPoint(string symbol, decimal p) { // get index for symbol int idx = symidx(symbol); // setup parameters OffsetInfo trail = null; decimal refp = 0; // see if we trail this symbol if ((idx == NOSYM) && _trailbydefault) { // get parameters idx = _trail.Count; refp = p; trail = new OffsetInfo(_defaulttrail); // save them _symidx.Add(symbol, idx); _ref.Add(refp); _pendingfill.Add(false); firecount.addindex(symbol, 0); esize.addindex(symbol, pt[symbol].UnsignedSize); // just in case user is modifying on seperate thread lock (_trail) { _trail.Add(trail); } D(symbol + " trail tracking modified: " + trail.ToString()); } else if ((idx == NOSYM) && !_trailbydefault) { return; } else { // get parameters refp = _ref[idx]; // in case tracker started after trail stop should have been broken. if (refp == 0 && _pt[symbol].isValid) { refp = _pt[symbol].AvgPrice; } // just in case user tries to modify on seperate thread lock (_trail) { trail = _trail[idx]; } } // see if we need to update ref price if ((refp == 0) || (_pt[symbol].isLong && (refp < p)) || (_pt[symbol].isShort && (refp > p))) { // update refp = p; // save it _ref[idx] = refp; // notify v(symbol + " new reference price: " + p); } // see if we broke our trail var testdist = Math.Abs(refp - p); var trailtest = testdist > trail.StopDist; if (!_pendingfill[idx] && (trail.StopDist != 0) && trailtest && (MaxFireCount > firecount[idx])) { // notify D(symbol + " hit trailing stop at: " + p.ToString("F2")); // mark pending order _pendingfill[idx] = true; // get order Order flat = new MarketOrderFlat(_pt[symbol], trail.StopPercent, trail.NormalizeSize, trail.MinimumLotSize); // get order id flat.id = _id.AssignId; // adjust expectation esize[idx] -= flat.UnsignedSize; // count fire firecount[idx]++; // send flat order SendOrder(flat); // notify D(symbol + " enforcing trail with: " + flat.ToString() + " esize: " + esize[idx] + " count: " + firecount[idx]); if (HitOffset != null) { HitOffset(symbol, flat.id, p); } } else if (!_noverb) { if (_pendingfill[idx]) { v(symbol + " waiting for trail fill."); } else if (trail.StopDist == 0) { v(symbol + " trail has been disabled."); } else if (!trailtest) { v(symbol + " trail not hit, current dist: " + testdist + " trailamt: " + trail.StopDist); } else if (MaxFireCount > firecount[idx]) { v(symbol + " trail max fire reached at: " + firecount[idx] + " max: " + MaxFireCount); } } }
void doupdate(string sym) { // is update ignored? if (IgnoreUpdate(sym)) { return; } // wait till next tick if we send cancels bool sentcancel = false; // get our offset values OffsetInfo off = GetOffset(sym); // if we're up to date then quit if (off.isOffsetCurrent(_pt[sym])) { return; } // see if we have profit if (off.hasProfit) { // notify if (!off.ProfitcancelPending) { debug(string.Format("attempting profit cancel: {0} {1}", sym, off.ProfitId)); } // cancel existing profits cancel(off.ProfitId); // mark cancel pending off.ProfitcancelPending = true; // mark as sent sentcancel |= true; } // see if we have stop if (off.hasStop) { // notify if (!off.StopcancelPending) { debug(string.Format("attempting stop cancel: {0} {1}", sym, off.StopId)); } // cancel existing stops cancel(off.StopId); // mark cancel pending off.StopcancelPending = true; // mark as sent sentcancel |= true; } // wait till next tick if we sent cancel if (sentcancel) { return; } if (!off.hasProfit) { // since we have no stop, it's cancel can't be pending off.ProfitcancelPending = false; // get new profit Order profit = Calc.PositionProfit(_pt[sym], off.ProfitDist, off.ProfitPercent, off.NormalizeSize, off.MinimumLotSize); // mark size off.SentProfitSize = profit.size; // if it's valid, send and track it if (profit.isValid) { profit.id = Ids.AssignId; off.ProfitId = profit.id; SendOffset(profit); // notify debug(string.Format("sent new profit: {0} {1}", profit.id, profit.ToString())); } } if (!off.hasStop) { // since we have no stop, it's cancel can't be pending off.StopcancelPending = false; // get new stop Order stop = Calc.PositionStop(_pt[sym], off.StopDist, off.StopPercent, off.NormalizeSize, off.MinimumLotSize); // mark size off.SentStopSize = stop.size; // if it's valid, send and track if (stop.isValid) { stop.id = Ids.AssignId; off.StopId = stop.id; SendOffset(stop); // notify debug(string.Format("sent new stop: {0} {1}", stop.id, stop.ToString())); } } // make sure new offset info is reflected SetOffset(sym, off); }
public static Order PositionStop(Position p, OffsetInfo offset) { return PositionStop(p, offset.ProfitDist, offset.ProfitPercent); }
/// <summary> /// must pass ticks as received to this function, in order to have trailing stops executed at proper time. /// </summary> /// <param name="k"></param> public void GotTick(Tick k) { // see if we're turned on if (!isValid) return; // see if we can exit when trail is broken if (SendOrder == null) return; // see if we have anything to trail against if (_pt[k.symbol].isFlat) return; // only care about trades if (!k.isTrade) return; // get index for symbol int idx = symidx(k.symbol); // setup parameters OffsetInfo trail = null; decimal refp = 0; // see if we trail this symbol if ((idx == NOSYM) && _trailbydefault) { // get parameters idx = _trail.Count; refp = k.trade; trail = new OffsetInfo(_defaulttrail); // save them _symidx.Add(k.symbol, idx); _ref.Add(refp); _pendingfill.Add(false); // just in case user is modifying on seperate thread lock (_trail) { _trail.Add(trail); } D("trail tracking: " + k.symbol + " " + trail.ToString()); } else if ((idx == NOSYM) && !_trailbydefault) return; else { // get parameters refp = _ref[idx]; // just in case user tries to modify on seperate thread lock (_trail) { trail = _trail[idx]; } } // see if we need to update ref price if ((refp == 0) || (_pt[k.symbol].isLong && (refp < k.trade)) || (_pt[k.symbol].isShort && (refp > k.trade))) { // update refp = k.trade; // save it _ref[idx] = refp; } // see if we broke our trail if (!_pendingfill[idx] && (trail.StopDist!=0) && (Math.Abs(refp - k.trade) > trail.StopDist)) { // notify D("hit trailing stop at: " + k.trade.ToString("n2")); // mark pending order _pendingfill[idx] = true; // get order Order flat = new MarketOrderFlat(_pt[k.symbol], trail.StopPercent, trail.NormalizeSize, trail.MinimumLotSize); // get order id flat.id = _id.AssignId; // send flat order SendOrder(flat); // notify D("enforcing trail with: " + flat.ToString()); } }