@@ -29,6 +29,7 @@ protected static function getGraphQLQuery(string $query_name): string {
2929 case 'FetchIdentityHistoricalFinancials ' : return "query FetchIdentityHistoricalFinancials( \$identityId: ID!, \$currency: Currency!, \$startDate: Date, \$endDate: Date, \$first: Int, \$cursor: String, \$accountIds: [ID!]) { \n identity(id: \$identityId) { \n id \n financials(filter: {accounts: \$accountIds}) { \n historicalDaily( \n currency: \$currency \n startDate: \$startDate \n endDate: \$endDate \n first: \$first \n after: \$cursor \n ) { \n edges { \n node { \n ...IdentityHistoricalFinancials \n __typename \n } \n __typename \n } \n pageInfo { \n hasNextPage \n endCursor \n __typename \n } \n __typename \n } \n __typename \n } \n __typename \n } \n } \n\n fragment IdentityHistoricalFinancials on IdentityHistoricalDailyFinancials { \n date \n netLiquidationValueV2 { \n amount \n currency \n __typename \n } \n netDepositsV2 { \n amount \n currency \n __typename \n } \n __typename \n } " ;
3030 case 'FetchCorporateActionChildActivities ' : return "query FetchCorporateActionChildActivities( \$activityCanonicalId: String!) { \n corporateActionChildActivities( \n condition: {activityCanonicalId: \$activityCanonicalId} \n ) { \n nodes { \n ...CorporateActionChildActivity \n __typename \n } \n __typename \n } \n} \n\nfragment CorporateActionChildActivity on CorporateActionChildActivity { \n canonicalId \n activityCanonicalId \n assetName \n assetSymbol \n assetType \n entitlementType \n quantity \n currency \n price \n recordDate \n __typename \n} " ;
3131 case 'FetchBrokerageMonthlyStatementTransactions ' : return "query FetchBrokerageMonthlyStatementTransactions( \$period: String!, \$accountId: String!) { \n brokerageMonthlyStatements(period: \$period, accountId: \$accountId) { \n id \n statementType \n createdAt \n data { \n ... on BrokerageMonthlyStatementObject { \n ...BrokerageMonthlyStatementObject \n __typename \n } \n __typename \n } \n __typename \n } \n} \n\nfragment BrokerageMonthlyStatementObject on BrokerageMonthlyStatementObject { \n custodianAccountId \n activitiesPerCurrency { \n currency \n currentTransactions { \n ...BrokerageMonthlyStatementTransactions \n __typename \n } \n __typename \n } \n currentTransactions { \n ...BrokerageMonthlyStatementTransactions \n __typename \n } \n isMultiCurrency \n __typename \n} \n\nfragment BrokerageMonthlyStatementTransactions on BrokerageMonthlyStatementTransactions { \n balance \n cashMovement \n unit \n description \n transactionDate \n transactionType \n __typename \n} " ;
32+ case 'FetchIdentityPositions ' : return "query FetchIdentityPositions( \$identityId: ID!, \$currency: Currency!, \$first: Int, \$cursor: String, \$accountIds: [ID!], \$aggregated: Boolean, \$currencyOverride: CurrencyOverride, \$sort: PositionSort, \$sortDirection: PositionSortDirection, \$filter: PositionFilter, \$since: PointInTime, \$includeSecurity: Boolean = false, \$includeAccountData: Boolean = false, \$includeOneDayReturnsBaseline: Boolean = false) { \n identity(id: \$identityId) { \n id \n financials(filter: {accounts: \$accountIds}) { \n current(currency: \$currency) { \n id \n positions( \n first: \$first \n after: \$cursor \n aggregated: \$aggregated \n filter: \$filter \n sort: \$sort \n sortDirection: \$sortDirection \n ) { \n edges { \n node { \n ...PositionV2 \n __typename \n } \n __typename \n } \n pageInfo { \n hasNextPage \n endCursor \n __typename \n } \n totalCount \n status \n hasOptionsPosition \n hasCryptoPositionsOnly \n securityTypes \n securityCurrencies \n __typename \n } \n __typename \n } \n __typename \n } \n __typename \n } \n} \n\nfragment SecuritySummary on Security { \n ...SecuritySummaryDetails \n stock { \n ...StockSummary \n __typename \n } \n quoteV2(currency: null) { \n ...SecurityQuoteV2 \n __typename \n } \n optionDetails { \n ...OptionSummary \n __typename \n } \n __typename \n} \n\nfragment SecuritySummaryDetails on Security { \n id \n currency \n inactiveDate \n status \n wsTradeEligible \n equityTradingSessionType \n securityType \n active \n securityGroups { \n id \n name \n __typename \n } \n features \n logoUrl \n __typename \n} \n\nfragment StockSummary on Stock { \n name \n symbol \n primaryMic \n primaryExchange \n __typename \n} \n\nfragment StreamedSecurityQuoteV2 on UnifiedQuote { \n __typename \n securityId \n ask \n bid \n currency \n price \n sessionPrice \n quotedAsOf \n ... on EquityQuote { \n marketStatus \n askSize \n bidSize \n close \n high \n last \n lastSize \n low \n open \n mid \n volume: vol \n referenceClose \n __typename \n } \n ... on OptionQuote { \n marketStatus \n askSize \n bidSize \n close \n high \n last \n lastSize \n low \n open \n mid \n volume: vol \n breakEven \n inTheMoney \n liquidityStatus \n openInterest \n underlyingSpot \n __typename \n } \n} \n\nfragment SecurityQuoteV2 on UnifiedQuote { \n ...StreamedSecurityQuoteV2 \n previousBaseline \n __typename \n} \n\nfragment OptionSummary on Option { \n underlyingSecurity { \n ...UnderlyingSecuritySummary \n __typename \n } \n maturity \n osiSymbol \n expiryDate \n multiplier \n optionType \n strikePrice \n __typename \n} \n\nfragment UnderlyingSecuritySummary on Security { \n id \n stock { \n name \n primaryExchange \n primaryMic \n symbol \n __typename \n } \n __typename \n} \n\nfragment PositionLeg on PositionLeg { \n security { \n id \n ...SecuritySummary @include(if: \$includeSecurity) \n __typename \n } \n quantity \n positionDirection \n bookValue { \n amount \n currency \n __typename \n } \n totalValue(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n averagePrice { \n amount \n currency \n __typename \n } \n percentageOfAccount \n unrealizedReturns(since: \$since) { \n amount \n currency \n __typename \n } \n marketAveragePrice: averagePrice(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n marketBookValue: bookValue(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n marketUnrealizedReturns: unrealizedReturns(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n oneDayReturnsBaselineV2(currencyOverride: \$currencyOverride) @include(if: \$includeOneDayReturnsBaseline) { \n baseline { \n currency \n amount \n __typename \n } \n useDailyPriceChange \n __typename \n } \n __typename \n} \n\nfragment PositionV2 on PositionV2 { \n id \n quantity \n accounts @include(if: \$includeAccountData) { \n id \n __typename \n } \n percentageOfAccount \n positionDirection \n bookValue { \n amount \n currency \n __typename \n } \n averagePrice { \n amount \n currency \n __typename \n } \n marketAveragePrice: averagePrice(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n marketBookValue: bookValue(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n totalValue(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n unrealizedReturns(since: \$since) { \n amount \n currency \n __typename \n } \n marketUnrealizedReturns: unrealizedReturns(currencyOverride: \$currencyOverride) { \n amount \n currency \n __typename \n } \n security { \n id \n ...SecuritySummary @include(if: \$includeSecurity) \n __typename \n } \n oneDayReturnsBaselineV2(currencyOverride: \$currencyOverride) @include(if: \$includeOneDayReturnsBaseline) { \n baseline { \n currency \n amount \n __typename \n } \n useDailyPriceChange \n __typename \n } \n strategyType \n legs { \n ...PositionLeg \n __typename \n } \n __typename \n} " ;
3233 };
3334 }
3435
@@ -482,4 +483,32 @@ public function getStatementTransactions(string $account_id, string $period): ar
482483 }
483484 return $ transactions ;
484485 }
486+
487+ /**
488+ * Retrieve information on specific positions.
489+ *
490+ * @param string[]|NULL $security_ids List of Wealthsimple security ids. NULL will return all owned securities.
491+ * @param string $currency Currency to return the amounts in (CAD or USD).
492+ * @param bool $include_account_data Whether to include account data.
493+ *
494+ * @return object[] A list of positions by account.
495+ * @throws WSApiException
496+ */
497+ public function getIdentityPositions (?array $ security_ids = NULL , string $ currency = 'CAD ' , $ include_account_data = TRUE ): array {
498+ $ positions = $ this ->doGraphQLQuery (
499+ 'FetchIdentityPositions ' ,
500+ [
501+ 'identityId ' => $ this ->getTokenInfo ()->identity_canonical_id ,
502+ 'currency ' => $ currency ,
503+ 'filter ' => ['securityIds ' => $ security_ids ],
504+ 'includeAccountData ' => $ include_account_data
505+ ],
506+ 'identity.financials.current.positions.edges ' ,
507+ 'array ' ,
508+ );
509+ if (!is_array ($ positions )) {
510+ throw new WSApiException ("Unexpected response format to GraphQL query 'FetchIdentityPositions' " , 0 , $ positions );
511+ }
512+ return $ positions ;
513+ }
485514}
0 commit comments