future-private: add flash close position request
This commit is contained in:
parent
4d0a9ebe56
commit
e86854ca54
21
README.md
21
README.md
|
|
@ -109,6 +109,23 @@ if ($response->getStatusCode() === 200) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Flash Close Position
|
||||||
|
|
||||||
|
```php
|
||||||
|
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
||||||
|
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
$response = $api->flashClosePosition('19848247723672');
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
echo "Position flash closed successfully!";
|
||||||
|
echo "Position ID: " . $data['data']['positionId'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Get Future Kline Data
|
### Get Future Kline Data
|
||||||
|
|
||||||
```php
|
```php
|
||||||
|
|
@ -133,6 +150,7 @@ if ($response->getStatusCode() === 200) {
|
||||||
### Trading
|
### Trading
|
||||||
|
|
||||||
- `placeOrder(...)` - Place a new order with full support for all order types, take profit, stop loss, and position management
|
- `placeOrder(...)` - Place a new order with full support for all order types, take profit, stop loss, and position management
|
||||||
|
- `flashClosePosition(string $positionId)` - Flash close position by position ID
|
||||||
|
|
||||||
### Market Data
|
### Market Data
|
||||||
|
|
||||||
|
|
@ -152,6 +170,7 @@ if ($response->getStatusCode() === 200) {
|
||||||
- **Change Leverage**: 10 req/sec/uid
|
- **Change Leverage**: 10 req/sec/uid
|
||||||
- **Change Margin Mode**: 10 req/sec/uid
|
- **Change Margin Mode**: 10 req/sec/uid
|
||||||
- **Place Order**: 10 req/sec/uid
|
- **Place Order**: 10 req/sec/uid
|
||||||
|
- **Flash Close Position**: 5 req/sec/uid
|
||||||
|
|
||||||
## Error Handling
|
## Error Handling
|
||||||
|
|
||||||
|
|
@ -190,6 +209,7 @@ Run specific tests:
|
||||||
vendor/bin/pest tests/ChangeLeverageTest.php
|
vendor/bin/pest tests/ChangeLeverageTest.php
|
||||||
vendor/bin/pest tests/ChangeMarginModeTest.php
|
vendor/bin/pest tests/ChangeMarginModeTest.php
|
||||||
vendor/bin/pest tests/PlaceOrderTest.php
|
vendor/bin/pest tests/PlaceOrderTest.php
|
||||||
|
vendor/bin/pest tests/FlashClosePositionTest.php
|
||||||
vendor/bin/pest tests/HeaderTest.php
|
vendor/bin/pest tests/HeaderTest.php
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -200,6 +220,7 @@ See the `examples/` directory for complete usage examples:
|
||||||
- `ChangeLeverageExample.php`
|
- `ChangeLeverageExample.php`
|
||||||
- `ChangeMarginModeExample.php`
|
- `ChangeMarginModeExample.php`
|
||||||
- `PlaceOrderExample.php`
|
- `PlaceOrderExample.php`
|
||||||
|
- `FlashClosePositionExample.php`
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example usage of Flash Close Position functionality
|
||||||
|
*
|
||||||
|
* This example demonstrates how to use the LaravelBitunixApi package
|
||||||
|
* to flash close positions on Bitunix exchange.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__.'/../vendor/autoload.php';
|
||||||
|
|
||||||
|
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
||||||
|
|
||||||
|
// Example configuration (in real usage, these would be in your .env file)
|
||||||
|
config([
|
||||||
|
'bitunix-api.future_base_uri' => 'https://fapi.bitunix.com/',
|
||||||
|
'bitunix-api.api_key' => 'your-api-key-here',
|
||||||
|
'bitunix-api.api_secret' => 'your-api-secret-here',
|
||||||
|
'bitunix-api.language' => 'en-US',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the API instance
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
echo "⚡ Flash Close Position Examples\n\n";
|
||||||
|
|
||||||
|
// Example 1: Flash close a single position
|
||||||
|
echo "1. Flash closing position...\n";
|
||||||
|
$positionId = '19848247723672';
|
||||||
|
|
||||||
|
$response = $api->flashClosePosition($positionId);
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
echo "✅ Position flash closed successfully!\n";
|
||||||
|
echo "Position ID: " . $data['data']['positionId'] . "\n";
|
||||||
|
} else {
|
||||||
|
echo "❌ API Error: " . $data['msg'] . "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "❌ HTTP Error: " . $response->getStatusCode() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
// Example 2: Flash close multiple positions
|
||||||
|
echo "2. Flash closing multiple positions...\n";
|
||||||
|
$positionIds = [
|
||||||
|
'19848247723672',
|
||||||
|
'19848247723673',
|
||||||
|
'19848247723674'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($positionIds as $positionId) {
|
||||||
|
echo "Closing position: {$positionId}...\n";
|
||||||
|
|
||||||
|
$response = $api->flashClosePosition($positionId);
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
echo "✅ Position {$positionId} closed successfully!\n";
|
||||||
|
} else {
|
||||||
|
echo "❌ Failed to close position {$positionId}: " . $data['msg'] . "\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "❌ HTTP Error for position {$positionId}: " . $response->getStatusCode() . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
// Example 3: Error handling
|
||||||
|
echo "3. Error handling example...\n";
|
||||||
|
$invalidPositionId = 'invalid-position-id';
|
||||||
|
|
||||||
|
$response = $api->flashClosePosition($invalidPositionId);
|
||||||
|
|
||||||
|
if ($response->getStatusCode() === 200) {
|
||||||
|
$data = json_decode($response->getBody()->getContents(), true);
|
||||||
|
if ($data['code'] === 0) {
|
||||||
|
echo "✅ Position closed successfully!\n";
|
||||||
|
} else {
|
||||||
|
echo "❌ API Error: " . $data['msg'] . "\n";
|
||||||
|
echo "This is expected for invalid position ID\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "❌ HTTP Error: " . $response->getStatusCode() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo '❌ Exception: '.$e->getMessage()."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flash Close Position Features:
|
||||||
|
*
|
||||||
|
* - Closes position by position ID
|
||||||
|
* - Rate limit: 5 req/sec/uid
|
||||||
|
* - Immediate position closure
|
||||||
|
* - No additional parameters required
|
||||||
|
*
|
||||||
|
* Important Notes:
|
||||||
|
*
|
||||||
|
* - Position ID must be valid and exist
|
||||||
|
* - Position must be open to be closed
|
||||||
|
* - This is an immediate action (flash close)
|
||||||
|
* - Use with caution as it closes positions immediately
|
||||||
|
*
|
||||||
|
* Environment Variables Required:
|
||||||
|
*
|
||||||
|
* BITUNIX_API_KEY=your-api-key
|
||||||
|
* BITUNIX_API_SECRET=your-api-secret
|
||||||
|
* BITUNIX_LANGUAGE=en-US
|
||||||
|
*/
|
||||||
|
|
@ -5,12 +5,13 @@ namespace Msr\LaravelBitunixApi;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use Msr\LaravelBitunixApi\Requests\ChangeLeverageRequestContract;
|
use Msr\LaravelBitunixApi\Requests\ChangeLeverageRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||||
|
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\Header;
|
use Msr\LaravelBitunixApi\Requests\Header;
|
||||||
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
class LaravelBitunixApi implements ChangeLeverageRequestContract, ChangeMarginModeRequestContract, FutureKLineRequestContract, PlaceOrderRequestContract
|
class LaravelBitunixApi implements ChangeLeverageRequestContract, ChangeMarginModeRequestContract, FlashClosePositionRequestContract, FutureKLineRequestContract, PlaceOrderRequestContract
|
||||||
{
|
{
|
||||||
private Client $publicFutureClient;
|
private Client $publicFutureClient;
|
||||||
|
|
||||||
|
|
@ -153,4 +154,17 @@ class LaravelBitunixApi implements ChangeLeverageRequestContract, ChangeMarginMo
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function flashClosePosition(string $positionId): ResponseInterface
|
||||||
|
{
|
||||||
|
$body = [
|
||||||
|
'positionId' => $positionId,
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->getPrivateFutureClient([], $body)->post('trade/flash_close_position', [
|
||||||
|
'json' => $body,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace Msr\LaravelBitunixApi;
|
||||||
use Msr\LaravelBitunixApi\Commands\LaravelBitunixApiCommand;
|
use Msr\LaravelBitunixApi\Commands\LaravelBitunixApiCommand;
|
||||||
use Msr\LaravelBitunixApi\Requests\ChangeLeverageRequestContract;
|
use Msr\LaravelBitunixApi\Requests\ChangeLeverageRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
use Msr\LaravelBitunixApi\Requests\ChangeMarginModeRequestContract;
|
||||||
|
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
use Msr\LaravelBitunixApi\Requests\FutureKLineRequestContract;
|
||||||
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
use Msr\LaravelBitunixApi\Requests\PlaceOrderRequestContract;
|
||||||
use Spatie\LaravelPackageTools\Package;
|
use Spatie\LaravelPackageTools\Package;
|
||||||
|
|
@ -35,5 +36,6 @@ class LaravelBitunixApiServiceProvider extends PackageServiceProvider
|
||||||
$this->app->bind(ChangeLeverageRequestContract::class, LaravelBitunixApi::class);
|
$this->app->bind(ChangeLeverageRequestContract::class, LaravelBitunixApi::class);
|
||||||
$this->app->bind(ChangeMarginModeRequestContract::class, LaravelBitunixApi::class);
|
$this->app->bind(ChangeMarginModeRequestContract::class, LaravelBitunixApi::class);
|
||||||
$this->app->bind(PlaceOrderRequestContract::class, LaravelBitunixApi::class);
|
$this->app->bind(PlaceOrderRequestContract::class, LaravelBitunixApi::class);
|
||||||
|
$this->app->bind(FlashClosePositionRequestContract::class, LaravelBitunixApi::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Msr\LaravelBitunixApi\Requests;
|
||||||
|
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
|
interface FlashClosePositionRequestContract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Flash close position by position ID
|
||||||
|
*
|
||||||
|
* @param string $positionId Position ID
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function flashClosePosition(string $positionId): ResponseInterface;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Msr\LaravelBitunixApi\Requests\FlashClosePositionRequestContract;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
config([
|
||||||
|
'bitunix-api.future_base_uri' => 'https://fapi.bitunix.com/',
|
||||||
|
'bitunix-api.api_key' => 'test-api-key',
|
||||||
|
'bitunix-api.api_secret' => 'test-secret-key',
|
||||||
|
'bitunix-api.language' => 'en-US',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can flash close position successfully', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
expect(fn() => $api->flashClosePosition('19848247723672'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates required position ID parameter', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
// Test with valid position ID
|
||||||
|
expect(fn() => $api->flashClosePosition('19848247723672'))
|
||||||
|
->not->toThrow(Exception::class)
|
||||||
|
->and(fn() => $api->flashClosePosition('123456789'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle different position ID formats', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
$positionIds = [
|
||||||
|
'19848247723672',
|
||||||
|
'123456789',
|
||||||
|
'987654321',
|
||||||
|
'position-123',
|
||||||
|
'pos_456'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($positionIds as $positionId) {
|
||||||
|
expect(fn() => $api->flashClosePosition($positionId))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates position ID parameter type', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
// Test with string position ID
|
||||||
|
expect(fn() => $api->flashClosePosition('19848247723672'))
|
||||||
|
->not->toThrow(Exception::class)
|
||||||
|
->and(fn() => $api->flashClosePosition('123456789'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle edge cases for position ID', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
// Test with long position ID
|
||||||
|
expect(fn() => $api->flashClosePosition('198482477236721234567890'))
|
||||||
|
->not->toThrow(Exception::class)
|
||||||
|
->and(fn() => $api->flashClosePosition('123'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates flash close position method exists', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
expect(method_exists($api, 'flashClosePosition'))->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle multiple flash close position calls', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
$positionIds = ['19848247723672', '19848247723673', '19848247723674'];
|
||||||
|
|
||||||
|
foreach ($positionIds as $positionId) {
|
||||||
|
expect(fn() => $api->flashClosePosition($positionId))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates flash close position response structure', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
// This test verifies the method can be called without throwing exceptions
|
||||||
|
// The actual response structure will be validated by the API
|
||||||
|
expect(fn() => $api->flashClosePosition('19848247723672'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can handle special characters in position ID', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
// Test with position ID containing special characters
|
||||||
|
expect(fn() => $api->flashClosePosition('pos-123_456'))
|
||||||
|
->not->toThrow(Exception::class)
|
||||||
|
->and(fn() => $api->flashClosePosition('pos.123.456'))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates flash close position with empty string', function () {
|
||||||
|
$api = app(FlashClosePositionRequestContract::class);
|
||||||
|
|
||||||
|
// This should not throw an exception at the method level
|
||||||
|
// The API will handle validation
|
||||||
|
expect(fn() => $api->flashClosePosition(''))
|
||||||
|
->not->toThrow(Exception::class);
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue