Skip to content

Commit a6ac4a9

Browse files
committed
Initial solution
1 parent cad5f20 commit a6ac4a9

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
using QuantConnect.Data;
6+
using QuantConnect.Interfaces;
7+
using QuantConnect.Orders;
8+
9+
namespace QuantConnect.Algorithm.CSharp
10+
{
11+
public class UpdateStopOrdersRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition
12+
{
13+
private OrderTicket _ticket;
14+
15+
public override void Initialize()
16+
{
17+
SetStartDate(2018, 4, 3);
18+
SetEndDate(2018, 4, 4);
19+
20+
AddForex("EURUSD", Resolution.Minute);
21+
}
22+
23+
public override void OnData(Slice data)
24+
{
25+
if (!Portfolio.Invested)
26+
{
27+
var qty = CalculateOrderQuantity("EURUSD", 50m);
28+
29+
MarketOrder("EURUSD", qty);
30+
31+
_ticket = StopMarketOrder("EURUSD", -qty / 2, Securities["EURUSD"].Price - 0.003m);
32+
33+
Log($"Before TotalMarginUsed: {Portfolio.TotalMarginUsed}");
34+
35+
var updateSettings = new UpdateOrderFields
36+
{
37+
Quantity = -qty * 10,
38+
StopPrice = Securities["EURUSD"].Price - 0.003m
39+
};
40+
var response = _ticket.Update(updateSettings);
41+
42+
if (response.IsSuccess)
43+
{
44+
Log($"After TotalMarginUsed: {Portfolio.TotalMarginUsed}");
45+
}
46+
}
47+
}
48+
49+
public override void OnOrderEvent(OrderEvent orderEvent)
50+
{
51+
var order = Transactions.GetOrderById(orderEvent.OrderId);
52+
if (order.Type == OrderType.StopMarket && orderEvent.Status == OrderStatus.Filled)
53+
{
54+
_ticket = null;
55+
}
56+
}
57+
/// <summary>
58+
/// Final status of the algorithm
59+
/// </summary>
60+
public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed;
61+
62+
/// <summary>
63+
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
64+
/// </summary>
65+
public bool CanRunLocally { get; } = true;
66+
67+
/// <summary>
68+
/// This is used by the regression test system to indicate which languages this algorithm is written in.
69+
/// </summary>
70+
public virtual List<Language> Languages { get; } = new() { Language.CSharp };
71+
72+
/// <summary>
73+
/// Data Points count of all timeslices of algorithm
74+
/// </summary>
75+
public long DataPoints => 2893;
76+
77+
/// <summary>
78+
/// Data Points count of the algorithm history
79+
/// </summary>
80+
public int AlgorithmHistoryDataPoints => 60;
81+
82+
/// <summary>
83+
/// This is used by the regression test system to indicate what the expected statistics are from running the algorithm
84+
/// </summary>
85+
public Dictionary<string, string> ExpectedStatistics => new Dictionary<string, string>
86+
{
87+
{"Total Orders", "3"},
88+
{"Average Win", "0%"},
89+
{"Average Loss", "0%"},
90+
{"Compounding Annual Return", "0%"},
91+
{"Drawdown", "0%"},
92+
{"Expectancy", "0"},
93+
{"Start Equity", "100000.00"},
94+
{"End Equity", "91982.00"},
95+
{"Net Profit", "0%"},
96+
{"Sharpe Ratio", "0"},
97+
{"Sortino Ratio", "0"},
98+
{"Probabilistic Sharpe Ratio", "0%"},
99+
{"Loss Rate", "0%"},
100+
{"Win Rate", "0%"},
101+
{"Profit-Loss Ratio", "0"},
102+
{"Alpha", "0"},
103+
{"Beta", "0"},
104+
{"Annual Standard Deviation", "0"},
105+
{"Annual Variance", "0"},
106+
{"Information Ratio", "0"},
107+
{"Tracking Error", "0"},
108+
{"Treynor Ratio", "0"},
109+
{"Total Fees", "$0.00"},
110+
{"Estimated Strategy Capacity", "$250000.00"},
111+
{"Lowest Capacity Asset", "EURUSD 8G"},
112+
{"Portfolio Turnover", "3074.60%"},
113+
{"OrderListHash", "373a8b2323b0fa4c15c80cd1abd25dd3"}
114+
};
115+
}
116+
}

Engine/TransactionHandlers/BrokerageTransactionHandler.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,16 @@ private OrderResponse HandleUpdateOrderRequest(UpdateOrderRequest request)
967967

968968
ticket.SetOrder(order);
969969

970+
var hasSufficientBuyingPowerResult = _algorithm.Portfolio.HasSufficientBuyingPowerForOrder([order]);
971+
972+
if (!hasSufficientBuyingPowerResult.IsSufficient)
973+
{
974+
var errorMessage = $@"Order Error: id: [{order.Id}], Insufficient buying power to complete order, Reason: {hasSufficientBuyingPowerResult.Reason}.";
975+
_algorithm.Error(errorMessage);
976+
InvalidateOrders([order], errorMessage);
977+
return OrderResponse.Error(request, OrderResponseErrorCode.InsufficientBuyingPower, errorMessage);
978+
}
979+
970980
bool orderUpdated;
971981
if (isClosedOrderUpdate)
972982
{

0 commit comments

Comments
 (0)