public void ExitPosition(GF.Api.Positions.IPosition position, GF.Api.Positions.PositionChangedEventArgs e) { var volume = GetPositionVolume(position); var side = volume > 0 ? OrderSide.Sell : OrderSide.BuyToCover; Console.WriteLine("Initiating order..."); PlaceOrder(gfClient, e.ContractPosition.Contract.ElectronicContract, OrderSide.Sell, Math.Abs(volume)); }
//Helper function for cat_Trail private double get_position_pnl(GF.Api.IGFClient client, GF.Api.Positions.PositionChangedEventArgs e) { //SEEMS LIKE IT NEEDS A LOOP... NO? //foreach(var pos in GF.Api.Positions....) return(e.ContractPosition.OTE); //+ e.ContractPosition.Gain; //Think Gain is Realized PNL, we want UNREALIZED only. //THINK from documentation that it's only OTE for OpenPNL }
//THIS SHOULD BE CALLED ON TICK MOST LIKELY... whereas the entries on BARS public int check_ts_cs(GF.Api.Positions.PositionChangedEventArgs e) { //Called inside of loop of positions in Array : ) var opl = get_position_pnl(gfClient, e); var sym = e.ContractPosition.Contract.Symbol; //Default dict values ... (used in if/elifs) var def = false; var idef = 0.0; //If no value in dict, save them in -- (Avoid errors) if (hi_pnl.TryGetValue(sym, out idef)) //Make sure this doesnt write over any current value? { hi_pnl[sym] = 0; trigger_pnl[sym] = 0; } //If new high, write over past hi_pnl if (opl > hi_pnl[sym]) //MIGHT need to init this dictionary when position opens? { hi_pnl[sym] = opl; } //Update Trigger price... trigger_pnl[sym] = hi_pnl[sym] * (1 - trail_dec); //Begin Trailing with Trigger... if (opl >= trail_tgt) { if (!trail_on.TryGetValue(sym, out def)) { trail_on[sym] = true; } } if (trail_on[sym]) { if (opl <= trigger_pnl[sym]) { Console.WriteLine($"Exitting {sym} at {opl}"); //PlaceOrder(gfClient, e.ContractPosition.Contract.ElectronicContract, OrderSide.BuyToCover); -- Replace w MKT order (or STOP ordeR?) return(1); //signals time to exit... and logs -- Cleaner. } } if (opl <= fixed_stop) { return(-1); } return(0); }
//Hidden Entry into the program -- This initializes the RUN. private void GFClient_OnAvgPositionChanged(GF.Api.IGFClient client, GF.Api.Positions.PositionChangedEventArgs e) { //Connect c; For static call to shit // IFF -- This is called ONCE, replace run_cat_trail with RUN() here -- //Run(e); run_cat_trail(e); //Can throw RUN in here!! Since I can;t get it to run otherwise... Also does nice logging. -- OR just call check_ts_cs right from here. Console.WriteLine( "Average Position. {0}/{1}: Net Pos: {2} @ {3}, Bought: {4}, Sold {5}, Prev Pos: {6} P/L: {7:c}", e.Account.Spec, e.ContractPosition.Contract.Symbol, e.ContractPosition.Net.Volume, e.ContractPosition.Net.Price, e.ContractPosition.Long.Volume, e.ContractPosition.Short.Volume, e.ContractPosition.Prev.Volume, e.ContractPosition.OTE + e.ContractPosition.Gain); }
public int run_cat_trail(GF.Api.Positions.PositionChangedEventArgs e) { //var account = gfClient.Accounts.Get().FirstOrDefault(); //Should be inside loop ? Called inside loop? //var positions = GetOpenPositions(account, e); //Just in case we need more detail / Safety... int ret = 0; foreach (var pos in e.AsArray()) { ret = check_ts_cs(pos); switch (ret) { case 0: break; case -1: Console.WriteLine($"CatStop Triggered -- Exiting position in {e.ContractPosition.Contract.Symbol}"); break; case 1: Console.WriteLine($"TrailStop Triggered -- Exiting position in {e.ContractPosition.Contract.Symbol}"); break; default: Console.WriteLine($"Error -- Please check position in {e.ContractPosition.Contract.Symbol}"); break; } if (ret != 0) { var qty = Math.Abs(e.ContractPosition.Net.Volume); if (e.ContractPosition.Net.Volume < 0) { PlaceOrder(gfClient, e.ContractPosition.Contract.ElectronicContract, OrderSide.BuyToCover, qty); Console.WriteLine("SX order sent."); } if (e.ContractPosition.Net.Volume > 0) { PlaceOrder(gfClient, e.ContractPosition.Contract.ElectronicContract, OrderSide.Sell, qty); Console.WriteLine("LX order sent."); } } } return(ret); }
//Helper function to simplify run_cat_trail function... -- BETTER version in closeposition logic... public int Go_Flat(GF.Api.Positions.PositionChangedEventArgs e) { var symbol = e.ContractPosition.Contract.Symbol; var net_basis = e.ContractPosition.Net.Volume; int _basis = net_basis > 0 ? 1 : -1; var close_qty = Math.Abs(net_basis); Console.WriteLine($"Exitting Position in -- {symbol}"); switch (_basis) { case -1: PlaceOrder(gfClient, e.ContractPosition.Contract.ElectronicContract, OrderSide.BuyToCover, close_qty); return(0); case 1: PlaceOrder(gfClient, e.ContractPosition.Contract.ElectronicContract, OrderSide.Sell, close_qty); return(0); default: return(-1); } }
public IEnumerable <GF.Api.Positions.IPosition> GetOpenPositions(GF.Api.Accounts.IAccount account, GF.Api.Positions.PositionChangedEventArgs e) { //Made active an ATTRIBUTE / PROPERTY -- now can be called whenever. //GF.Api.Positions.IPosition[] active = { }; //Should I make this a fixed memory level ? Will Dynamic create overflow? int idx = 0; foreach (var pos in e.AsArray()) { //If Matched Account, Has fills, and has Open Position PNL... Add to active. if (e.ContractPosition.Account.ID == account.ID & e.ContractPosition.Fills != null & e.ContractPosition.OTE != 0) { //Console.WriteLine(pos); active[idx] = pos.ContractPosition; } idx += 1; } //Real purpose -- return changed positions -- > To feed into TrailStop. return(active); }
/*Initially -- Try to use JUST the above code... IF you require more detail, then integrate the below stuff (tweaked examples) */ //Goal was to find and loop thrugh all open positions... return them as an iterable object -- upon PositionsChangedEvent public IEnumerable <GF.Api.Positions.IPosition> GetPositions(GF.Api.Accounts.IAccount account, GF.Api.Positions.PositionChangedEventArgs e) { return(e.ContractPosition.AsArray()); }
//Need to get this PositionChangedEventArg shit somewhere ? No clue where... public void Run(GF.Api.Positions.PositionChangedEventArgs e, int EOD = 1600, int sleep_seconds = 5) { //Gets Datetime and uses inf loop to check for new positions, and manage the trailstop -- Eventually could also use OnBar for entries. //Maybe should be using onBar bc new position only on bars... DateTime now = DateTime.Now; DateTime saveUtcNow = DateTime.UtcNow; //If needed later... TimeSpan FUT_gap = new TimeSpan(0, 2, 0, 0); //0 days, 10 hours, 5 minutes and 1 second //tempDate.ToString("MMMM dd, yyyy") var ns = now.ToString("HH:mm:ss"); Console.WriteLine("Checking for Market Open..."); if (now.Hour == EOD) { Console.WriteLine("Waiting for Market Reopen."); } while (now.Hour == EOD) { now = DateTime.Now; Thread.Sleep(1000 * 60 * 5); //5min Sleep -- waiting for re-open } Console.WriteLine("Market now Open."); RegisterOnAvgPositionChanged(gfClient); //Hopefully starts the event loop? -- THIS COULD BE WAY OFF //Replaced delay with sleep -- simpler. // TimeSpan object with 0 days, 0 hours, 0 minutes and (SLEEP arg) seconds. //TimeSpan delay = new System.TimeSpan(0, 0, 0, sleep_seconds); //DateTime next = now + delay; while (true) { now = DateTime.Now; //need to call heartbeat? (runner?) //Check if Closed FIRST -- so don't accidentally exit in non-hours if (now.Hour == EOD) { now = DateTime.Now; Thread.Sleep(1000 * 60 * 60); } //Entry Stuff / OnBar could also be called right here... might want to check that flat tho (return from onBar?) //if(now > next) //next = DateTime.Now + delay; ns = now.ToString("HH:mm:ss"); Debug.WriteLine($"Calling run_cat_trail -- {ns}"); var call = run_cat_trail(e); Debug.WriteLine($"{call}"); Thread.Sleep(sleep_seconds * 1000); Debug.WriteLine("Iteration Done ..."); } }
public static void Test(GF.Api.Positions.PositionChangedEventArgs e) { Console.WriteLine("Testing event shit."); }