diff --git a/src/FFT.Oanda/Accounts/AccountFinancingMode.cs b/src/FFT.Oanda/Accounts/AccountFinancingMode.cs index 5f9e78a..ea6baef 100644 --- a/src/FFT.Oanda/Accounts/AccountFinancingMode.cs +++ b/src/FFT.Oanda/Accounts/AccountFinancingMode.cs @@ -25,4 +25,12 @@ public enum AccountFinancingMode /// Account daily at 5pm New York time. /// DAILY, + + /// + /// Not in the Oanda API documentation but in my transaction history + /// + DAILY_FINANCING, + DAILY_INSTRUMENT, + SECOND_BY_SECOND_COMPONENT, + } diff --git a/src/FFT.Oanda/Accounts/AccountSummary.cs b/src/FFT.Oanda/Accounts/AccountSummary.cs index bdeaff6..5a23c27 100644 --- a/src/FFT.Oanda/Accounts/AccountSummary.cs +++ b/src/FFT.Oanda/Accounts/AccountSummary.cs @@ -51,7 +51,7 @@ public record AccountSummary /// /// The date/time that the account’s resettablePL was last reset. /// - [JsonConverter(typeof(ResettablePLDateConverter))] + // [JsonConverter(typeof(ResettablePLDateConverter))] blows up the response if you call OandaApiClient.GetAccountSummary, ResettablePLTime comes with default dateTime spec in json data public DateTime? ResettablePLTime { get; init; } /// diff --git a/src/FFT.Oanda/Instruments/Candlestick.cs b/src/FFT.Oanda/Instruments/Candlestick.cs index 989d359..c24d975 100644 --- a/src/FFT.Oanda/Instruments/Candlestick.cs +++ b/src/FFT.Oanda/Instruments/Candlestick.cs @@ -35,7 +35,7 @@ public sealed record CandleStick /// The number of prices created during the time-range represented by the /// candlestick. /// - public double Volume { get; init; } + public decimal Volume { get; init; } // no reason to use double /// /// A flag indicating if the candlestick is complete. A complete candlestick diff --git a/src/FFT.Oanda/Instruments/CandlestickData.cs b/src/FFT.Oanda/Instruments/CandlestickData.cs index 8524d00..7eef654 100644 --- a/src/FFT.Oanda/Instruments/CandlestickData.cs +++ b/src/FFT.Oanda/Instruments/CandlestickData.cs @@ -13,24 +13,24 @@ public sealed record CandlestickData /// The first (open) price in the time-range represented by the candlestick. /// [JsonPropertyName("o")] - public required double Open { get; init; } + public required decimal Open { get; init; } /// /// The highest price in the time-range represented by the candlestick. /// [JsonPropertyName("h")] - public required double High { get; init; } + public required decimal High { get; init; } /// /// The lowest price in the time-range represented by the candlestick. /// [JsonPropertyName("l")] - public required double Low { get; init; } + public required decimal Low { get; init; } /// /// A flag indicating if the candlestick is complete. A complete candlestick /// is one whose ending time is not in the future. /// [JsonPropertyName("c")] - public required double Close { get; init; } + public required decimal Close { get; init; } } diff --git a/src/FFT.Oanda/OandaApiClient.cs b/src/FFT.Oanda/OandaApiClient.cs index 25b5de0..543187a 100644 --- a/src/FFT.Oanda/OandaApiClient.cs +++ b/src/FFT.Oanda/OandaApiClient.cs @@ -1277,7 +1277,10 @@ public IAsyncEnumerable GetTransactionStreamSince(string accountId, // Immediately calling MoveNextAsync is required to get the stream to actually connect and start receiving messages. await using var liveStream = GetTransactionsStream(accountId, cts.Token).GetAsyncEnumerator(cts.Token); - var liveStreamMoveNext = liveStream.MoveNextAsync(cts.Token); + + // var liveStreamMoveNext = liveStream.MoveNextAsync(cts.Token); + var liveStreamMoveNext = liveStream.MoveNextAsync(); // at least in Net8 the call is parameterless + await Task.Delay(1000, cts.Token); // Give the live stream time to establish before downloading transactions from the past. var rangeReponse = await GetTransactionIdRange(accountId, from, null, cts.Token); @@ -1294,13 +1297,18 @@ public IAsyncEnumerable GetTransactionStreamSince(string accountId, } while (await liveStreamMoveNext && liveStream.Current.Id <= lastTransactionId) - liveStreamMoveNext = liveStream.MoveNextAsync(cts.Token); + { + // liveStreamMoveNext = liveStream.MoveNextAsync(cts.Token); + liveStreamMoveNext = liveStream.MoveNextAsync(); // at least in Net8 the call is parameterless + } } while (await liveStreamMoveNext) { await result.Writer.WriteAsync(liveStream.Current, cts.Token); // TODO: Throw exception if writing is blocked a long time due to slow reading by consumer. - liveStreamMoveNext = liveStream.MoveNextAsync(cts.Token); + + // liveStreamMoveNext = liveStream.MoveNextAsync(cts.Token); + liveStreamMoveNext = liveStream.MoveNextAsync(); // at least in Net8 the call is parameterless } result.Writer.Complete(); @@ -1574,19 +1582,35 @@ public async Task GetCandlestickData( int dailyAlignment = 17, string alignmentTimezone = "America/New_York", WeeklyAlignment weeklyAlignment = WeeklyAlignment.FRIDAY, - int units = 1, + // int units = 1, // not supported by the API CancellationToken cancellationToken = default) { candleSpecification.ThrowIfNull().Value.Validate(); count.Throw().IfOutOfRange(500, 5000); to?.Throw().IfDateTimeKindNot(DateTimeKind.Utc); from?.Throw().IfDateTimeKindNot(DateTimeKind.Utc); - (includeFirst.HasValue == from.HasValue).Throw().IfFalse(); // includeFirst is required with from, and must not be set if from is not set. - (from.HasValue && to.HasValue).Throw().IfTrue(); + + // includeFirst is required with from, and must not be set if from is not set. + // (includeFirst.HasValue == from.HasValue).Throw().IfFalse(); + // instead of throwing an exception better to use default + // else you always have to set the parameters bewteen from and includeFirst + if (from != null && from.HasValue) + { + if (includeFirst == null || !includeFirst.HasValue) + { + includeFirst = true; + } + } + + // (from.HasValue && to.HasValue).Throw().IfTrue(); + // why cut down the API features? + // it is usefull to have the option to get a specific area of candles between two timestamps + // at least I use that feature + dailyAlignment.Throw().IfOutOfRange(0, 23); alignmentTimezone.ThrowIfNull().Throw().IfWhiteSpace(); weeklyAlignment.Throw().IfOutOfRange(); - units.Throw().IfLessThan(1); + // units.Throw().IfLessThan(1); // Not supported by the API var query = new Dictionary { @@ -1596,10 +1620,16 @@ public async Task GetCandlestickData( { "dailyAlignment", dailyAlignment.ToString(InvariantCulture) }, { "alignmentTimezone", alignmentTimezone }, { "weeklyAlignment", weeklyAlignment.ToString() }, - { "units", units.ToString(InvariantCulture) }, - { "count", count.ToString(InvariantCulture) }, + // { "units", units.ToString(InvariantCulture) }, // is not supported by the API + // { "count", count.ToString(InvariantCulture) }, // should not be send in any case }; + // count is not allowed if both of 'to' and 'from' are set + if ((to == null) || (from == null)) + { + query.Add("count", count.ToString(InvariantCulture)); + } + if (to.HasValue) query.Add("to", to.Value.ToString(DATETIMEFORMATSTRING, InvariantCulture)); if (from.HasValue) query.Add("from", from.Value.ToString(DATETIMEFORMATSTRING, InvariantCulture)); if (includeFirst.HasValue) query.Add("includeFirst", includeFirst.Value.ToString()); diff --git a/src/FFT.Oanda/Orders/Order.cs b/src/FFT.Oanda/Orders/Order.cs index 723c0a4..1b8d4ee 100644 --- a/src/FFT.Oanda/Orders/Order.cs +++ b/src/FFT.Oanda/Orders/Order.cs @@ -17,170 +17,176 @@ namespace FFT.Oanda.Orders; [JsonConverter(typeof(OrderConverter))] public abstract record Order { - /// - /// The Order’s identifier, unique within the Order’s Account. - /// - public required int Id { get; init; } - - /// - /// The time when the Order was created. - /// - public required DateTime CreateTime { get; init; } - - /// - /// The current state of the Order. - /// - public required OrderState State { get; init; } - - /// - /// The client extensions of the Order. Do not set, modify, or delete - /// clientExtensions if your account is associated with MT4. - /// - public required ClientExtensions? ClientExtensions { get; init; } - - /// - /// The type of the Order. - /// - public required OrderType Type { get; init; } - - /// - /// The Order’s Instrument. - /// - public required string Instrument { get; init; } - - /// - /// The time-in-force requested for the Order. - /// - public required TimeInForce TimeInForce { get; init; } - - /// - /// The date/time when the Order will be cancelled if its timeInForce - /// is “GTD”. - /// - public required DateTime? GtdTime { get; init; } - - /// - /// Specification of how Positions in the Account are modified when the - /// Order is filled. - /// - public required OrderPositionFill PositionFill { get; init; } - - /// - /// Specification of which price component should be used when determining - /// if an Order should be triggered and filled. This allows Orders to be - /// triggered based on the bid, ask, mid, default (ask for buy, bid for - /// sell) or inverse (ask for sell, bid for buy) price depending on the - /// desired behaviour. Orders are always filled using their default price - /// component. This feature is only provided through the REST API. Clients - /// who choose to specify a non-default trigger condition will not see it - /// reflected in any of OANDA’s proprietary or partner trading platforms, - /// their transaction history or their account statements. OANDA platforms - /// always assume that an Order’s trigger condition is set to the default - /// value when indicating the distance from an Order’s trigger price, and - /// will always provide the default trigger condition when creating or - /// modifying an Order. A special restriction applies when creating a - /// Guaranteed Stop Loss Order. In this case the TriggerCondition value must - /// either be “DEFAULT”, or the“natural” trigger side “DEFAULT” results in. - /// So for a Guaranteed Stop Loss Order for a long trade valid values are - /// “DEFAULT” and “BID”, and for short trades “DEFAULT” and “ASK” are valid. - /// - public required OrderTriggerCondition TriggerCondition { get; init; } - - /// - /// TakeProfitDetails specifies the details of a Take Profit Order to be - /// created on behalf of a client. This may happen when an Order is filled - /// that opens a Trade requiring a Take Profit, or when a Trade’s dependent - /// Take Profit Order is modified directly through the Trade. - /// - public required TakeProfitDetails? TakeProfitOnFill { get; init; } - - /// - /// StopLossDetails specifies the details of a Stop Loss Order to be created - /// on behalf of a client. This may happen when an Order is filled that - /// opens a Trade requiring a Stop Loss, or when a Trade’s dependent Stop - /// Loss Order is modified directly through the Trade. - /// - public required StopLossDetails? StopLossOnFill { get; init; } - - /// - /// GuaranteedStopLossDetails specifies the details of a Guaranteed Stop - /// Loss Order to be created on behalf of a client. This may happen when an - /// Order is filled that opens a Trade requiring a Guaranteed Stop Loss, or - /// when a Trade’s dependent Guaranteed Stop Loss Order is modified directly - /// through the Trade. - /// - public required GuaranteedStopLossDetails? GuaranteedStopLossOnFill { get; init; } - - /// - /// TrailingStopLossDetails specifies the details of a Trailing Stop Loss - /// Order to be created on behalf of a client. This may happen when an Order - /// is filled that opens a Trade requiring a Trailing Stop Loss, or when a - /// Trade’s dependent Trailing Stop Loss Order is modified directly through - /// the Trade. - /// - public required TrailingStopLossDetails? TrailingStopLossOnFill { get; init; } - - /// - /// Client Extensions to add to the Trade created when the Order is filled - /// (if such a Trade is created). Do not set, modify, or delete - /// tradeClientExtensions if your account is associated with MT4. - /// - public required ClientExtensions? TradeClientExtensions { get; init; } - - /// - /// ID of the Transaction that filled this Order (only provided when the - /// Order’s state is FILLED). - /// - public required int? FillingTransactionID { get; init; } - - /// - /// Date/time when the Order was filled (only provided when the Order’s - /// state is FILLED). - /// - public required DateTime? FilledTime { get; init; } - - /// - /// Trade ID of Trade opened when the Order was filled (only provided when - /// the Order’s state is FILLED and a Trade was opened as a result of the - /// fill). - /// - public required int? TradeOpenedID { get; init; } - - /// - /// Trade ID of Trade reduced when the Order was filled (Only provided when - /// the Order’s state is FILLED and a Trade was reduced as a result of the - /// fill). - /// - public required int? TradeReducedID { get; init; } - - /// - /// Trade IDs of Trades closed when the Order was filled (Only provided when - /// the Order’s state is FILLED and one or more Trades were closed as a - /// result of the fill). - /// - public required ImmutableList? TradeClosedIDs { get; init; } - - /// - /// ID of the Transaction that cancelled the Order (Only provided when the - /// Order’s state is CANCELLED). - /// - public required int? CancellingTransactionID { get; init; } - - /// - /// Date/time when the Order was cancelled (only provided when the state of - /// the Order is CANCELLED). - /// - public required DateTime? CancelledTime { get; init; } - - /// - /// The ID of the Order that was replaced by this Order (only provided if - /// this Order was created as part of a cancel/replace). - /// - public required int? ReplacesOrderID { get; init; } - - /// - /// The ID of the Order that replaced this Order (only provided if this - /// Order was cancelled as part of a cancel/replace). - /// - public required int? ReplacedByOrderID { get; init; } -} + +// due to order derived classes are used in the trade object as properties with only partial information +// most of the properties arent allowed to be set required +// these properties doesnt exists in the trades object json stream +// seems that only six of them will be send by oanda every time ... +// Id, CreateTime, State, Type, TimeInForce and TriggerCondition + + /// + /// The Order’s identifier, unique within the Order’s Account. + /// + public required int Id { get; init; } + + /// + /// The time when the Order was created. + /// + public required DateTime CreateTime { get; init; } + + /// + /// The current state of the Order. + /// + public required OrderState State { get; init; } + + /// + /// The client extensions of the Order. Do not set, modify, or delete + /// clientExtensions if your account is associated with MT4. + /// + public ClientExtensions? ClientExtensions { get; init; } + + /// + /// The type of the Order. + /// + public required OrderType Type { get; init; } + + /// + /// The Order’s Instrument. + /// + public string Instrument { get; init; } + + /// + /// The time-in-force requested for the Order. + /// + public required TimeInForce TimeInForce { get; init; } + + /// + /// The date/time when the Order will be cancelled if its timeInForce + /// is “GTD”. + /// + public DateTime? GtdTime { get; init; } + + /// + /// Specification of how Positions in the Account are modified when the + /// Order is filled. + /// + public OrderPositionFill PositionFill { get; init; } + + /// + /// Specification of which price component should be used when determining + /// if an Order should be triggered and filled. This allows Orders to be + /// triggered based on the bid, ask, mid, default (ask for buy, bid for + /// sell) or inverse (ask for sell, bid for buy) price depending on the + /// desired behaviour. Orders are always filled using their default price + /// component. This feature is only provided through the REST API. Clients + /// who choose to specify a non-default trigger condition will not see it + /// reflected in any of OANDA’s proprietary or partner trading platforms, + /// their transaction history or their account statements. OANDA platforms + /// always assume that an Order’s trigger condition is set to the default + /// value when indicating the distance from an Order’s trigger price, and + /// will always provide the default trigger condition when creating or + /// modifying an Order. A special restriction applies when creating a + /// Guaranteed Stop Loss Order. In this case the TriggerCondition value must + /// either be “DEFAULT”, or the“natural” trigger side “DEFAULT” results in. + /// So for a Guaranteed Stop Loss Order for a long trade valid values are + /// “DEFAULT” and “BID”, and for short trades “DEFAULT” and “ASK” are valid. + /// + public required OrderTriggerCondition TriggerCondition { get; init; } + + /// + /// TakeProfitDetails specifies the details of a Take Profit Order to be + /// created on behalf of a client. This may happen when an Order is filled + /// that opens a Trade requiring a Take Profit, or when a Trade’s dependent + /// Take Profit Order is modified directly through the Trade. + /// + public TakeProfitDetails? TakeProfitOnFill { get; init; } + + /// + /// StopLossDetails specifies the details of a Stop Loss Order to be created + /// on behalf of a client. This may happen when an Order is filled that + /// opens a Trade requiring a Stop Loss, or when a Trade’s dependent Stop + /// Loss Order is modified directly through the Trade. + /// + public StopLossDetails? StopLossOnFill { get; init; } + + /// + /// GuaranteedStopLossDetails specifies the details of a Guaranteed Stop + /// Loss Order to be created on behalf of a client. This may happen when an + /// Order is filled that opens a Trade requiring a Guaranteed Stop Loss, or + /// when a Trade’s dependent Guaranteed Stop Loss Order is modified directly + /// through the Trade. + /// + public GuaranteedStopLossDetails? GuaranteedStopLossOnFill { get; init; } + + /// + /// TrailingStopLossDetails specifies the details of a Trailing Stop Loss + /// Order to be created on behalf of a client. This may happen when an Order + /// is filled that opens a Trade requiring a Trailing Stop Loss, or when a + /// Trade’s dependent Trailing Stop Loss Order is modified directly through + /// the Trade. + /// + public TrailingStopLossDetails? TrailingStopLossOnFill { get; init; } + + /// + /// Client Extensions to add to the Trade created when the Order is filled + /// (if such a Trade is created). Do not set, modify, or delete + /// tradeClientExtensions if your account is associated with MT4. + /// + public ClientExtensions? TradeClientExtensions { get; init; } + + /// + /// ID of the Transaction that filled this Order (only provided when the + /// Order’s state is FILLED). + /// + public int? FillingTransactionID { get; init; } + + /// + /// Date/time when the Order was filled (only provided when the Order’s + /// state is FILLED). + /// + public DateTime? FilledTime { get; init; } + + /// + /// Trade ID of Trade opened when the Order was filled (only provided when + /// the Order’s state is FILLED and a Trade was opened as a result of the + /// fill). + /// + public int? TradeOpenedID { get; init; } + + /// + /// Trade ID of Trade reduced when the Order was filled (Only provided when + /// the Order’s state is FILLED and a Trade was reduced as a result of the + /// fill). + /// + public int? TradeReducedID { get; init; } + + /// + /// Trade IDs of Trades closed when the Order was filled (Only provided when + /// the Order’s state is FILLED and one or more Trades were closed as a + /// result of the fill). + /// + public ImmutableList? TradeClosedIDs { get; init; } + + /// + /// ID of the Transaction that cancelled the Order (Only provided when the + /// Order’s state is CANCELLED). + /// + public int? CancellingTransactionID { get; init; } + + /// + /// Date/time when the Order was cancelled (only provided when the state of + /// the Order is CANCELLED). + /// + public DateTime? CancelledTime { get; init; } + + /// + /// The ID of the Order that was replaced by this Order (only provided if + /// this Order was created as part of a cancel/replace). + /// + public int? ReplacesOrderID { get; init; } + + /// + /// The ID of the Order that replaced this Order (only provided if this + /// Order was cancelled as part of a cancel/replace). + /// + public int? ReplacedByOrderID { get; init; }} diff --git a/src/FFT.Oanda/Orders/OrderPositionFill.cs b/src/FFT.Oanda/Orders/OrderPositionFill.cs index 9d248a7..fb5b0f3 100644 --- a/src/FFT.Oanda/Orders/OrderPositionFill.cs +++ b/src/FFT.Oanda/Orders/OrderPositionFill.cs @@ -10,6 +10,13 @@ namespace FFT.Oanda.Orders; [JsonConverter(typeof(JsonStringEnumConverter))] public enum OrderPositionFill { + + /// + /// When the Order is filled, use REDUCE_FIRST behaviour for non-client + /// hedging Accounts, and OPEN_ONLY behaviour for client hedging Accounts. + /// + DEFAULT, // moved to first place so it will be used as initialization + /// /// When the Order is filled, only allow Positions to be opened or extended. /// @@ -26,9 +33,4 @@ public enum OrderPositionFill /// REDUCE_ONLY, - /// - /// When the Order is filled, use REDUCE_FIRST behaviour for non-client - /// hedging Accounts, and OPEN_ONLY behaviour for client hedging Accounts. - /// - DEFAULT, } diff --git a/src/FFT.Oanda/Orders/OrderRequests/LimitOrderRequest.cs b/src/FFT.Oanda/Orders/OrderRequests/LimitOrderRequest.cs index e578bf9..162c2d6 100644 --- a/src/FFT.Oanda/Orders/OrderRequests/LimitOrderRequest.cs +++ b/src/FFT.Oanda/Orders/OrderRequests/LimitOrderRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) True Goodwill. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using FFT.Oanda.JsonConverters; + namespace FFT.Oanda.Orders.OrderRequests; /// @@ -17,6 +19,7 @@ public sealed record LimitOrderRequest : OpenTradeOrderRequest /// number of units results in a long Order, and a negative number of units /// results in a short Order. /// + [JsonConverter(typeof(DecimalStringConverter))] // order request is rejected without public decimal Units { get; init; } /// @@ -24,6 +27,7 @@ public sealed record LimitOrderRequest : OpenTradeOrderRequest /// only be filled by a market price that is equal to or better than this /// price. /// + [JsonConverter(typeof(DecimalStringConverter))] // order request is rejected without public decimal Price { get; init; } private protected override void CustomValidate2() diff --git a/src/FFT.Oanda/Orders/OrderRequests/MarketIfTouchedOrderRequest.cs b/src/FFT.Oanda/Orders/OrderRequests/MarketIfTouchedOrderRequest.cs index 716fcd4..e77f678 100644 --- a/src/FFT.Oanda/Orders/OrderRequests/MarketIfTouchedOrderRequest.cs +++ b/src/FFT.Oanda/Orders/OrderRequests/MarketIfTouchedOrderRequest.cs @@ -1,6 +1,8 @@ // Copyright (c) True Goodwill. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using FFT.Oanda.JsonConverters; + namespace FFT.Oanda.Orders.OrderRequests; /// @@ -19,6 +21,14 @@ public sealed record MarketIfTouchedOrderRequest : OpenTradeOrderRequest /// public override OrderType Type => OrderType.MARKET_IF_TOUCHED; + /// + /// The quantity requested to be filled by the MarketIfTouched Order. A positive + /// number of units results in a long Order, and a negative number of units + /// results in a short Order. + /// + [JsonConverter(typeof(DecimalStringConverter))] + public decimal Units { get; init; } + /// /// The price threshold specified for the MarketIfTouched Order. The /// MarketIfTouched Order will only be filled by a market price that crosses @@ -27,6 +37,7 @@ public sealed record MarketIfTouchedOrderRequest : OpenTradeOrderRequest /// the Order’s price and initialMarketPrice, the MarketIfTouchedOrder will /// behave like a Limit or a Stop Order. /// + [JsonConverter(typeof(DecimalStringConverter))] // order request is rejected without public decimal Price { get; init; } /// diff --git a/src/FFT.Oanda/Pricing/ClientPrice.cs b/src/FFT.Oanda/Pricing/ClientPrice.cs index d38bfb8..4a5c69c 100644 --- a/src/FFT.Oanda/Pricing/ClientPrice.cs +++ b/src/FFT.Oanda/Pricing/ClientPrice.cs @@ -22,7 +22,10 @@ public sealed record ClientPrice /// /// The date/time when the Price was created. /// - [JsonPropertyName("timestamp")] + + // Due to Oanda API documentation the property name shoukd be 'time' + // at least in the TickStream ClientPrice objects thats the case, else the TickStream will not work + // [JsonPropertyName("timestamp")] public DateTime Time { get; init; } /// diff --git a/src/FFT.Oanda/Transactions/DividendAdjustmentTransaction.cs b/src/FFT.Oanda/Transactions/DividendAdjustmentTransaction.cs index 5d31690..d4eb0f4 100644 --- a/src/FFT.Oanda/Transactions/DividendAdjustmentTransaction.cs +++ b/src/FFT.Oanda/Transactions/DividendAdjustmentTransaction.cs @@ -12,7 +12,7 @@ public sealed record DividendAdjustmentTransaction : Transaction /// /// The name of the instrument for the dividendAdjustment transaction. /// - public string Instrument { get; } + public string Instrument { get; init; } /// /// The total dividend adjustment amount paid or collected in the Account’s @@ -21,7 +21,7 @@ public sealed record DividendAdjustmentTransaction : Transaction /// adjustments paid/collected for each OpenTradeDividendAdjustment found /// within the Transaction. Expressed in the account's home currency. /// - public decimal DividendAdjustment { get; } + public decimal DividendAdjustment { get; init; } /// /// The total dividend adjustment amount paid or collected in the @@ -30,24 +30,24 @@ public sealed record DividendAdjustmentTransaction : Transaction /// adjustments paid/collected for each OpenTradeDividendAdjustment found /// within the Transaction. /// - public decimal QuoteDividendAdjustment { get; } + public decimal QuoteDividendAdjustment { get; init; } /// /// The HomeConversionFactors in effect at the time of the /// DividendAdjustment. /// - public HomeConversionFactors HomeConversionFactors { get; } + public HomeConversionFactors HomeConversionFactors { get; init; } /// /// The Account balance after applying the DividendAdjustment Transaction. /// Expressed in the account's home currency. /// - public decimal AccountBalance { get; } + public decimal AccountBalance { get; init; } /// /// The dividend adjustment payment/collection details for each open Trade, /// within the Account, for which a dividend adjustment is to be paid or /// collected. /// - public ImmutableList OpenTradeDividendAdjustments { get; } + public ImmutableList OpenTradeDividendAdjustments { get; init; } } diff --git a/src/FFT.Oanda/Transactions/FundingReason.cs b/src/FFT.Oanda/Transactions/FundingReason.cs index 277f3c1..183af1b 100644 --- a/src/FFT.Oanda/Transactions/FundingReason.cs +++ b/src/FFT.Oanda/Transactions/FundingReason.cs @@ -33,4 +33,9 @@ public enum FundingReason /// Funds are being transferred as part of an Account adjustment /// ADJUSTMENT, + + /// + /// Not in the Oanda API documentation but in my transaction history + /// + LEGACY_ACCOUNT_TRANSFER, }