@@ -1329,28 +1329,41 @@ public override object describe()
13291329 { "fillResponseFromRequest" , true } ,
13301330 } } ,
13311331 { "fetchOHLCV" , new Dictionary < string , object > ( ) {
1332- { "spot" , new Dictionary < string , object > ( ) {
1333- { "method" , "publicSpotGetV2SpotMarketCandles" } ,
1334- } } ,
1335- { "swap" , new Dictionary < string , object > ( ) {
1336- { "method" , "publicMixGetV2MixMarketCandles" } ,
1337- } } ,
1338- { "maxDaysPerTimeframe" , new Dictionary < string , object > ( ) {
1332+ { "maxRecentDaysPerTimeframe" , new Dictionary < string , object > ( ) {
13391333 { "1m" , 30 } ,
13401334 { "3m" , 30 } ,
13411335 { "5m" , 30 } ,
1342- { "10m" , 30 } ,
1343- { "15m" , 52 } ,
1344- { "30m" , 62 } ,
1345- { "1h" , 83 } ,
1346- { "2h" , 120 } ,
1336+ { "15m" , 30 } ,
1337+ { "30m" , 30 } ,
1338+ { "1h" , 60 } ,
13471339 { "4h" , 240 } ,
13481340 { "6h" , 360 } ,
1349- { "12h" , 360 } ,
1350- { "1d" , 300 } ,
1351- { "3d" , 300 } ,
1352- { "1w" , 300 } ,
1353- { "1M" , 300 } ,
1341+ { "12h" , 720 } ,
1342+ { "1d" , 1440 } ,
1343+ { "3d" , multiply ( 1440 , 3 ) } ,
1344+ { "1w" , multiply ( 1440 , 7 ) } ,
1345+ { "1M" , multiply ( 1440 , 30 ) } ,
1346+ } } ,
1347+ { "spot" , new Dictionary < string , object > ( ) {
1348+ { "maxLimitPerTimeframe" , new Dictionary < string , object > ( ) {
1349+ { "1d" , 300 } ,
1350+ { "3d" , 100 } ,
1351+ { "1w" , 100 } ,
1352+ { "1M" , 100 } ,
1353+ } } ,
1354+ { "method" , "publicSpotGetV2SpotMarketCandles" } ,
1355+ } } ,
1356+ { "swap" , new Dictionary < string , object > ( ) {
1357+ { "maxLimitPerTimeframe" , new Dictionary < string , object > ( ) {
1358+ { "4h" , 540 } ,
1359+ { "6h" , 360 } ,
1360+ { "12h" , 180 } ,
1361+ { "1d" , 90 } ,
1362+ { "3d" , 30 } ,
1363+ { "1w" , 13 } ,
1364+ { "1M" , 4 } ,
1365+ } } ,
1366+ { "method" , "publicMixGetV2MixMarketCandles" } ,
13541367 } } ,
13551368 } } ,
13561369 { "fetchTrades" , new Dictionary < string , object > ( ) {
@@ -1544,7 +1557,7 @@ public override object describe()
15441557 { "symbolRequired" , false } ,
15451558 } } ,
15461559 { "fetchOHLCV" , new Dictionary < string , object > ( ) {
1547- { "limit" , 1000 } ,
1560+ { "limit" , 200 } ,
15481561 } } ,
15491562 } } ,
15501563 { "forPerps" , new Dictionary < string , object > ( ) {
@@ -1621,14 +1634,11 @@ public virtual object handleProductTypeAndParams(object market = null, object pa
16211634 if ( isTrue ( isTrue ( ( ! isEqual ( subType , null ) ) ) && isTrue ( ( isEqual ( market , null ) ) ) ) )
16221635 {
16231636 // set default only if subType is defined and market is not defined, since there is also USDC productTypes which are also linear
1624- object sandboxMode = this . safeBool ( this . options , "sandboxMode" , false ) ;
1625- if ( isTrue ( sandboxMode ) )
1626- {
1627- defaultProductType = ( ( bool ) isTrue ( ( isEqual ( subType , "linear" ) ) ) ) ? "SUSDT-FUTURES" : "SCOIN-FUTURES" ;
1628- } else
1629- {
1630- defaultProductType = ( ( bool ) isTrue ( ( isEqual ( subType , "linear" ) ) ) ) ? "USDT-FUTURES" : "COIN-FUTURES" ;
1631- }
1637+ // const sandboxMode = this.safeBool (this.options, 'sandboxMode', false);
1638+ // if (sandboxMode) {
1639+ // defaultProductType = (subType === 'linear') ? 'SUSDT-FUTURES' : 'SCOIN-FUTURES';
1640+ // } else {
1641+ defaultProductType = ( ( bool ) isTrue ( ( isEqual ( subType , "linear" ) ) ) ) ? "USDT-FUTURES" : "COIN-FUTURES" ;
16321642 }
16331643 object productType = this . safeString ( parameters , "productType" , defaultProductType ) ;
16341644 if ( isTrue ( isTrue ( ( isEqual ( productType , null ) ) ) && isTrue ( ( ! isEqual ( market , null ) ) ) ) )
@@ -3607,30 +3617,32 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
36073617 object market = this . market ( symbol ) ;
36083618 object marketType = ( ( bool ) isTrue ( getValue ( market , "spot" ) ) ) ? "spot" : "swap" ;
36093619 object timeframes = getValue ( getValue ( this . options , "timeframes" ) , marketType ) ;
3610- object msInDay = 86400000 ;
3611- object duration = multiply ( this . parseTimeframe ( timeframe ) , 1000 ) ;
36123620 object request = new Dictionary < string , object > ( ) {
36133621 { "symbol" , getValue ( market , "id" ) } ,
36143622 { "granularity" , this . safeString ( timeframes , timeframe , timeframe ) } ,
36153623 } ;
3624+ object msInDay = 86400000 ;
3625+ object now = this . milliseconds ( ) ;
3626+ object duration = multiply ( this . parseTimeframe ( timeframe ) , 1000 ) ;
36163627 object until = this . safeInteger ( parameters , "until" ) ;
36173628 object limitDefined = ! isEqual ( limit , null ) ;
36183629 object sinceDefined = ! isEqual ( since , null ) ;
36193630 object untilDefined = ! isEqual ( until , null ) ;
36203631 parameters = this . omit ( parameters , new List < object > ( ) { "until" } ) ;
3621- object response = null ;
3622- object now = this . milliseconds ( ) ;
36233632 // retrievable periods listed here:
36243633 // - https://www.bitget.com/api-doc/spot/market/Get-Candle-Data#request-parameters
36253634 // - https://www.bitget.com/api-doc/contract/market/Get-Candle-Data#description
3626- object ohlcOptions = this . safeDict ( this . options , "fetchOHLCV" , new Dictionary < string , object > ( ) { } ) ;
3627- object retrievableDaysMap = this . safeDict ( ohlcOptions , "maxDaysPerTimeframe" , new Dictionary < string , object > ( ) { } ) ;
3628- object maxRetrievableDaysForRecent = this . safeInteger ( retrievableDaysMap , timeframe , 30 ) ; // default to safe minimum
3629- object endpointTsBoundary = subtract ( now , multiply ( ( subtract ( maxRetrievableDaysForRecent , 1 ) ) , msInDay ) ) ;
3635+ object key = ( ( bool ) isTrue ( getValue ( market , "spot" ) ) ) ? "spot" : "swap" ;
3636+ object ohlcOptions = this . safeDict ( getValue ( this . options , "fetchOHLCV" ) , key , new Dictionary < string , object > ( ) { } ) ;
3637+ object maxLimitPerTimeframe = this . safeDict ( ohlcOptions , "maxLimitPerTimeframe" , new Dictionary < string , object > ( ) { } ) ;
3638+ object maxLimitForThisTimeframe = this . safeInteger ( maxLimitPerTimeframe , timeframe , limit ) ;
3639+ object recentEndpointDaysMap = this . safeDict ( getValue ( this . options , "fetchOHLCV" ) , "maxRecentDaysPerTimeframe" , new Dictionary < string , object > ( ) { } ) ;
3640+ object recentEndpointAvailableDays = this . safeInteger ( recentEndpointDaysMap , timeframe ) ;
3641+ object recentEndpointBoundaryTs = subtract ( now , multiply ( ( subtract ( recentEndpointAvailableDays , 1 ) ) , msInDay ) ) ;
36303642 if ( isTrue ( limitDefined ) )
36313643 {
36323644 limit = mathMin ( limit , maxLimitForRecentEndpoint ) ;
3633- ( ( IDictionary < string , object > ) request ) [ " limit" ] = limit ;
3645+ limit = mathMin ( limit , maxLimitForThisTimeframe ) ;
36343646 } else
36353647 {
36363648 limit = defaultLimit ;
@@ -3659,20 +3671,36 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
36593671 calculatedStartTime = subtract ( calculatedEndTime , limitMultipliedDuration ) ;
36603672 }
36613673 }
3662- object historicalEndpointNeeded = isTrue ( ( ! isEqual ( calculatedStartTime , null ) ) ) && isTrue ( ( isLessThanOrEqual ( calculatedStartTime , endpointTsBoundary ) ) ) ;
3663- if ( isTrue ( historicalEndpointNeeded ) )
3674+ // if historical endpoint is needed, we should re-set the variables
3675+ object historicalEndpointNeeded = false ;
3676+ if ( isTrue ( isTrue ( ( isTrue ( ! isEqual ( calculatedStartTime , null ) ) && isTrue ( isLessThanOrEqual ( calculatedStartTime , recentEndpointBoundaryTs ) ) ) ) || isTrue ( useHistoryEndpoint ) ) )
36643677 {
3678+ historicalEndpointNeeded = true ;
36653679 // only for "historical-candles" - ensure we use correct max limit
3666- if ( isTrue ( limitDefined ) )
3667- {
3668- ( ( IDictionary < string , object > ) request ) [ "limit" ] = mathMin ( limit , maxLimitForHistoryEndpoint ) ;
3680+ limit = mathMin ( limit , maxLimitForHistoryEndpoint ) ;
3681+ limitMultipliedDuration = multiply ( limit , duration ) ;
3682+ calculatedStartTime = subtract ( calculatedEndTime , limitMultipliedDuration ) ;
3683+ ( ( IDictionary < string , object > ) request ) [ "startTime" ] = calculatedStartTime ;
3684+ // for contract, maximum 90 days allowed between start-end times
3685+ if ( ! isTrue ( getValue ( market , "spot" ) ) )
3686+ {
3687+ object maxDistanceDaysForContracts = 90 ;
3688+ // only correct if request is larger
3689+ if ( isTrue ( isGreaterThan ( subtract ( calculatedEndTime , calculatedStartTime ) , multiply ( maxDistanceDaysForContracts , msInDay ) ) ) )
3690+ {
3691+ calculatedEndTime = this . sum ( calculatedStartTime , multiply ( maxDistanceDaysForContracts , msInDay ) ) ;
3692+ ( ( IDictionary < string , object > ) request ) [ "endTime" ] = calculatedEndTime ;
3693+ }
36693694 }
36703695 }
3696+ // we need to set limit to safely cover the period
3697+ ( ( IDictionary < string , object > ) request ) [ "limit" ] = limit ;
36713698 // make request
3699+ object response = null ;
36723700 if ( isTrue ( getValue ( market , "spot" ) ) )
36733701 {
36743702 // checks if we need history endpoint
3675- if ( isTrue ( isTrue ( historicalEndpointNeeded ) || isTrue ( useHistoryEndpoint ) ) )
3703+ if ( isTrue ( historicalEndpointNeeded ) )
36763704 {
36773705 response = await this . publicSpotGetV2SpotMarketHistoryCandles ( this . extend ( request , parameters ) ) ;
36783706 } else
@@ -3681,18 +3709,6 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
36813709 }
36823710 } else
36833711 {
3684- object maxDistanceDaysForContracts = 90 ; // for contract, maximum 90 days allowed between start-end times
3685- // only correct the request to fix 90 days if until was auto-calculated
3686- if ( isTrue ( sinceDefined ) )
3687- {
3688- if ( ! isTrue ( untilDefined ) )
3689- {
3690- ( ( IDictionary < string , object > ) request ) [ "endTime" ] = mathMin ( calculatedEndTime , this . sum ( since , multiply ( maxDistanceDaysForContracts , msInDay ) ) ) ;
3691- } else if ( isTrue ( isGreaterThan ( subtract ( calculatedEndTime , calculatedStartTime ) , multiply ( maxDistanceDaysForContracts , msInDay ) ) ) )
3692- {
3693- throw new BadRequest ( ( string ) add ( add ( add ( this . id , " fetchOHLCV() between start and end must be less than " ) , ( ( object ) maxDistanceDaysForContracts ) . ToString ( ) ) , " days" ) ) ;
3694- }
3695- }
36963712 object priceType = null ;
36973713 var priceTypeparametersVariable = this . handleParamString ( parameters , "price" ) ;
36983714 priceType = ( ( IList < object > ) priceTypeparametersVariable ) [ 0 ] ;
@@ -3712,7 +3728,7 @@ public async override Task<object> fetchOHLCV(object symbol, object timeframe =
37123728 response = await this . publicMixGetV2MixMarketHistoryIndexCandles ( extended ) ;
37133729 } else
37143730 {
3715- if ( isTrue ( isTrue ( historicalEndpointNeeded ) || isTrue ( useHistoryEndpoint ) ) )
3731+ if ( isTrue ( historicalEndpointNeeded ) )
37163732 {
37173733 response = await this . publicMixGetV2MixMarketHistoryCandles ( extended ) ;
37183734 } else
0 commit comments