New eveal #32

Merged
Sirttas merged 115 commits from new-eveal into main 2026-07-14 17:15:11 +02:00
9 changed files with 373 additions and 125 deletions
Showing only changes of commit 925d9eef73 - Show all commits
+117 -6
View File
@@ -466,7 +466,8 @@ paths:
get: get:
tags: tags:
- market - market
summary: "Scan a single market type, returning its volume-weighted price quartiles" summary: "Scan a single market type, returning its volume-weighted price quartiles\
\ and recent price trend"
operationId: scanMarketType operationId: scanMarketType
parameters: parameters:
- name: marketTypeId - name: marketTypeId
@@ -497,12 +498,12 @@ paths:
minimum: 0 minimum: 0
- name: salesTax - name: salesTax
in: query in: query
description: "Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell\ description: "Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell\
\ orders" \ orders"
required: false required: false
schema: schema:
type: number type: number
default: 0.036 default: 0.03375
maximum: 1 maximum: 1
minimum: 0 minimum: 0
responses: responses:
@@ -548,6 +549,39 @@ paths:
$ref: "#/components/schemas/MarketHistoryResponse" $ref: "#/components/schemas/MarketHistoryResponse"
"400": "400":
description: The days parameter is not greater than 0 description: The days parameter is not greater than 0
/market/{marketTypeId}/history/quartiles:
get:
tags:
- market
summary: Compute volume-weighted price quartiles and the recent price trend
from a type's market history
operationId: findQuartiles
parameters:
- name: marketTypeId
in: path
description: Id of the market type
required: true
schema:
type: integer
format: int64
- name: days
in: query
description: Optional number of most recent days to analyze; omit for the
full history
required: false
schema:
type: integer
format: int32
minimum: 1
responses:
"200":
description: The price quartiles of the type
content:
'*/*':
schema:
$ref: "#/components/schemas/HistoryQuartilesResponse"
"400":
description: The days parameter is not greater than 0
/market/types: /market/types:
get: get:
tags: tags:
@@ -620,7 +654,7 @@ paths:
tags: tags:
- market - market
summary: "Scan every tracked market type, returning volume-weighted price quartiles\ summary: "Scan every tracked market type, returning volume-weighted price quartiles\
\ for each" \ and the recent price trend for each"
operationId: scanMarket operationId: scanMarket
parameters: parameters:
- name: days - name: days
@@ -644,12 +678,12 @@ paths:
minimum: 0 minimum: 0
- name: salesTax - name: salesTax
in: query in: query
description: "Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell\ description: "Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell\
\ orders" \ orders"
required: false required: false
schema: schema:
type: number type: number
default: 0.036 default: 0.03375
maximum: 1 maximum: 1
minimum: 0 minimum: 0
responses: responses:
@@ -694,6 +728,48 @@ paths:
Returned when: Returned when:
- the types parameter is missing - the types parameter is missing
- a types value is not a numeric id - a types value is not a numeric id
/market/history/quartiles:
get:
tags:
- market
summary: Compute volume-weighted price quartiles and the recent price trend
for each requested market type
operationId: findAllQuartiles
parameters:
- name: types
in: query
description: "Market type ids to analyze, e.g. types=34,35"
required: true
schema:
type: array
items:
type: integer
format: int64
- name: days
in: query
description: Optional number of most recent days to analyze; omit for the
full history
required: false
schema:
type: integer
format: int32
minimum: 1
responses:
"200":
description: "The price quartiles for each requested type, one entry per\
\ type"
content:
'*/*':
schema:
type: array
items:
$ref: "#/components/schemas/HistoryQuartilesResponse"
"400":
description: |-
Returned when:
- the types parameter is missing
- a types value is not a numeric id
- the days parameter is not greater than 0
/ledgers: /ledgers:
get: get:
tags: tags:
@@ -1126,6 +1202,12 @@ components:
totalVolume: totalVolume:
type: integer type: integer
format: int64 format: int64
trend:
type: string
enum:
- UP
- DOWN
- FLAT
profit: profit:
type: number type: number
score: score:
@@ -1140,6 +1222,7 @@ components:
- score - score
- sell - sell
- totalVolume - totalVolume
- trend
MarketHistoryResponse: MarketHistoryResponse:
type: object type: object
properties: properties:
@@ -1169,6 +1252,34 @@ components:
- marketTypeId - marketTypeId
- orderCount - orderCount
- volume - volume
HistoryQuartilesResponse:
type: object
properties:
marketTypeId:
type: integer
format: int64
q1:
type: number
median:
type: number
q3:
type: number
totalVolume:
type: integer
format: int64
trend:
type: string
enum:
- UP
- DOWN
- FLAT
required:
- marketTypeId
- median
- q1
- q3
- totalVolume
- trend
MarketTypeResponse: MarketTypeResponse:
type: object type: object
properties: properties:
+198 -16
View File
@@ -73,6 +73,23 @@ export interface CreateRuleBookRequest {
'ledgerRefs': Array<string>; 'ledgerRefs': Array<string>;
'script': string; 'script': string;
} }
export interface HistoryQuartilesResponse {
'marketTypeId': number;
'q1': number;
'median': number;
'q3': number;
'totalVolume': number;
'trend': HistoryQuartilesResponseTrendEnum;
}
export const HistoryQuartilesResponseTrendEnum = {
Up: 'UP',
Down: 'DOWN',
Flat: 'FLAT',
} as const;
export type HistoryQuartilesResponseTrendEnum = typeof HistoryQuartilesResponseTrendEnum[keyof typeof HistoryQuartilesResponseTrendEnum];
export interface IskTransferResponse extends TransferResponse { export interface IskTransferResponse extends TransferResponse {
'fromLedgerId': string; 'fromLedgerId': string;
'toLedgerId': string; 'toLedgerId': string;
@@ -121,9 +138,19 @@ export interface MarketScanResponse {
'median': number; 'median': number;
'q3': number; 'q3': number;
'totalVolume': number; 'totalVolume': number;
'trend': MarketScanResponseTrendEnum;
'profit': number; 'profit': number;
'score': number; 'score': number;
} }
export const MarketScanResponseTrendEnum = {
Up: 'UP',
Down: 'DOWN',
Flat: 'FLAT',
} as const;
export type MarketScanResponseTrendEnum = typeof MarketScanResponseTrendEnum[keyof typeof MarketScanResponseTrendEnum];
export interface MarketTypeResponse { export interface MarketTypeResponse {
'id': number; 'id': number;
'name': string; 'name': string;
@@ -1424,6 +1451,48 @@ export const MarketApiAxiosParamCreator = function (configuration?: Configuratio
options: localVarRequestOptions, options: localVarRequestOptions,
}; };
}, },
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend for each requested market type
* @param {Array<number>} types Market type ids to analyze, e.g. types&#x3D;34,35
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
findAllQuartiles: async (types: Array<number>, days?: number, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'types' is not null or undefined
assertParamExists('findAllQuartiles', 'types', types)
const localVarPath = `/market/history/quartiles`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
if (types) {
localVarQueryParameter['types'] = types;
}
if (days !== undefined) {
localVarQueryParameter['days'] = days;
}
localVarHeaderParameter['Accept'] = '*/*';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/** /**
* *
* @summary Find the market history of a type, most recent first * @summary Find the market history of a type, most recent first
@@ -1463,6 +1532,45 @@ export const MarketApiAxiosParamCreator = function (configuration?: Configuratio
options: localVarRequestOptions, options: localVarRequestOptions,
}; };
}, },
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend from a type\'s market history
* @param {number} marketTypeId Id of the market type
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
findQuartiles: async (marketTypeId: number, days?: number, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'marketTypeId' is not null or undefined
assertParamExists('findQuartiles', 'marketTypeId', marketTypeId)
const localVarPath = `/market/{marketTypeId}/history/quartiles`
.replace('{marketTypeId}', encodeURIComponent(String(marketTypeId)));
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
if (days !== undefined) {
localVarQueryParameter['days'] = days;
}
localVarHeaderParameter['Accept'] = '*/*';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/** /**
* *
* @summary Return the static market type details for each requested type id * @summary Return the static market type details for each requested type id
@@ -1537,10 +1645,10 @@ export const MarketApiAxiosParamCreator = function (configuration?: Configuratio
}, },
/** /**
* *
* @summary Scan every tracked market type, returning volume-weighted price quartiles for each * @summary Scan every tracked market type, returning volume-weighted price quartiles and the recent price trend for each
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1582,11 +1690,11 @@ export const MarketApiAxiosParamCreator = function (configuration?: Configuratio
}, },
/** /**
* *
* @summary Scan a single market type, returning its volume-weighted price quartiles * @summary Scan a single market type, returning its volume-weighted price quartiles and recent price trend
* @param {number} marketTypeId The market type id to scan * @param {number} marketTypeId The market type id to scan
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1693,6 +1801,20 @@ export const MarketApiFp = function(configuration?: Configuration) {
const localVarOperationServerBasePath = operationServerMap['MarketApi.currentPrices']?.[localVarOperationServerIndex]?.url; const localVarOperationServerBasePath = operationServerMap['MarketApi.currentPrices']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
}, },
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend for each requested market type
* @param {Array<number>} types Market type ids to analyze, e.g. types&#x3D;34,35
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async findAllQuartiles(types: Array<number>, days?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<HistoryQuartilesResponse>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.findAllQuartiles(types, days, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MarketApi.findAllQuartiles']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/** /**
* *
* @summary Find the market history of a type, most recent first * @summary Find the market history of a type, most recent first
@@ -1707,6 +1829,20 @@ export const MarketApiFp = function(configuration?: Configuration) {
const localVarOperationServerBasePath = operationServerMap['MarketApi.findHistory']?.[localVarOperationServerIndex]?.url; const localVarOperationServerBasePath = operationServerMap['MarketApi.findHistory']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath); return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
}, },
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend from a type\'s market history
* @param {number} marketTypeId Id of the market type
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async findQuartiles(marketTypeId: number, days?: number, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<HistoryQuartilesResponse>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.findQuartiles(marketTypeId, days, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['MarketApi.findQuartiles']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/** /**
* *
* @summary Return the static market type details for each requested type id * @summary Return the static market type details for each requested type id
@@ -1735,10 +1871,10 @@ export const MarketApiFp = function(configuration?: Configuration) {
}, },
/** /**
* *
* @summary Scan every tracked market type, returning volume-weighted price quartiles for each * @summary Scan every tracked market type, returning volume-weighted price quartiles and the recent price trend for each
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1750,11 +1886,11 @@ export const MarketApiFp = function(configuration?: Configuration) {
}, },
/** /**
* *
* @summary Scan a single market type, returning its volume-weighted price quartiles * @summary Scan a single market type, returning its volume-weighted price quartiles and recent price trend
* @param {number} marketTypeId The market type id to scan * @param {number} marketTypeId The market type id to scan
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1797,6 +1933,17 @@ export const MarketApiFactory = function (configuration?: Configuration, basePat
currentPrices(types: Array<number>, options?: RawAxiosRequestConfig): AxiosPromise<Array<MarketPriceResponse>> { currentPrices(types: Array<number>, options?: RawAxiosRequestConfig): AxiosPromise<Array<MarketPriceResponse>> {
return localVarFp.currentPrices(types, options).then((request) => request(axios, basePath)); return localVarFp.currentPrices(types, options).then((request) => request(axios, basePath));
}, },
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend for each requested market type
* @param {Array<number>} types Market type ids to analyze, e.g. types&#x3D;34,35
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
findAllQuartiles(types: Array<number>, days?: number, options?: RawAxiosRequestConfig): AxiosPromise<Array<HistoryQuartilesResponse>> {
return localVarFp.findAllQuartiles(types, days, options).then((request) => request(axios, basePath));
},
/** /**
* *
* @summary Find the market history of a type, most recent first * @summary Find the market history of a type, most recent first
@@ -1808,6 +1955,17 @@ export const MarketApiFactory = function (configuration?: Configuration, basePat
findHistory(marketTypeId: number, days?: number, options?: RawAxiosRequestConfig): AxiosPromise<Array<MarketHistoryResponse>> { findHistory(marketTypeId: number, days?: number, options?: RawAxiosRequestConfig): AxiosPromise<Array<MarketHistoryResponse>> {
return localVarFp.findHistory(marketTypeId, days, options).then((request) => request(axios, basePath)); return localVarFp.findHistory(marketTypeId, days, options).then((request) => request(axios, basePath));
}, },
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend from a type\'s market history
* @param {number} marketTypeId Id of the market type
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
findQuartiles(marketTypeId: number, days?: number, options?: RawAxiosRequestConfig): AxiosPromise<HistoryQuartilesResponse> {
return localVarFp.findQuartiles(marketTypeId, days, options).then((request) => request(axios, basePath));
},
/** /**
* *
* @summary Return the static market type details for each requested type id * @summary Return the static market type details for each requested type id
@@ -1830,10 +1988,10 @@ export const MarketApiFactory = function (configuration?: Configuration, basePat
}, },
/** /**
* *
* @summary Scan every tracked market type, returning volume-weighted price quartiles for each * @summary Scan every tracked market type, returning volume-weighted price quartiles and the recent price trend for each
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1842,11 +2000,11 @@ export const MarketApiFactory = function (configuration?: Configuration, basePat
}, },
/** /**
* *
* @summary Scan a single market type, returning its volume-weighted price quartiles * @summary Scan a single market type, returning its volume-weighted price quartiles and recent price trend
* @param {number} marketTypeId The market type id to scan * @param {number} marketTypeId The market type id to scan
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1882,6 +2040,18 @@ export class MarketApi extends BaseAPI {
return MarketApiFp(this.configuration).currentPrices(types, options).then((request) => request(this.axios, this.basePath)); return MarketApiFp(this.configuration).currentPrices(types, options).then((request) => request(this.axios, this.basePath));
} }
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend for each requested market type
* @param {Array<number>} types Market type ids to analyze, e.g. types&#x3D;34,35
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
public findAllQuartiles(types: Array<number>, days?: number, options?: RawAxiosRequestConfig) {
return MarketApiFp(this.configuration).findAllQuartiles(types, days, options).then((request) => request(this.axios, this.basePath));
}
/** /**
* *
* @summary Find the market history of a type, most recent first * @summary Find the market history of a type, most recent first
@@ -1894,6 +2064,18 @@ export class MarketApi extends BaseAPI {
return MarketApiFp(this.configuration).findHistory(marketTypeId, days, options).then((request) => request(this.axios, this.basePath)); return MarketApiFp(this.configuration).findHistory(marketTypeId, days, options).then((request) => request(this.axios, this.basePath));
} }
/**
*
* @summary Compute volume-weighted price quartiles and the recent price trend from a type\'s market history
* @param {number} marketTypeId Id of the market type
* @param {number} [days] Optional number of most recent days to analyze; omit for the full history
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
public findQuartiles(marketTypeId: number, days?: number, options?: RawAxiosRequestConfig) {
return MarketApiFp(this.configuration).findQuartiles(marketTypeId, days, options).then((request) => request(this.axios, this.basePath));
}
/** /**
* *
* @summary Return the static market type details for each requested type id * @summary Return the static market type details for each requested type id
@@ -1918,10 +2100,10 @@ export class MarketApi extends BaseAPI {
/** /**
* *
* @summary Scan every tracked market type, returning volume-weighted price quartiles for each * @summary Scan every tracked market type, returning volume-weighted price quartiles and the recent price trend for each
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1931,11 +2113,11 @@ export class MarketApi extends BaseAPI {
/** /**
* *
* @summary Scan a single market type, returning its volume-weighted price quartiles * @summary Scan a single market type, returning its volume-weighted price quartiles and recent price trend
* @param {number} marketTypeId The market type id to scan * @param {number} marketTypeId The market type id to scan
* @param {number} [days] Number of most recent days of history to analyse * @param {number} [days] Number of most recent days of history to analyse
* @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders * @param {number} [brokerFee] Broker fee as a fraction (e.g. 0.015 for 1.5%), paid on both buy and sell orders
* @param {number} [salesTax] Sales tax as a fraction (e.g. 0.036 for 3.6%), paid on sell orders * @param {number} [salesTax] Sales tax as a fraction (e.g. 0.03375 for 3.375%), paid on sell orders
* @param {*} [options] Override http request option. * @param {*} [options] Override http request option.
* @throws {RequiredError} * @throws {RequiredError}
*/ */
@@ -1,12 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import {LoadingSpinner, Tooltip} from '@/components'; import {LoadingSpinner, Tooltip} from '@/components';
import {formatIsk} from '@/formaters'; import {formatIsk} from '@/formaters';
import {getHistory, getHistoryQuartils} from '@/market'; import {getQuartiles, type HistoryQuartiles, MarketTrendIcon} from '@/market';
import {ArrowTrendingDownIcon, ArrowTrendingUpIcon} from '@heroicons/vue/24/outline';
import {computedAsync} from '@vueuse/core'; import {computedAsync} from '@vueuse/core';
import {ref, watchEffect} from 'vue'; import {computed, ref} from 'vue';
const trendingScale = 3;
interface Props { interface Props {
id: number; id: number;
@@ -17,42 +14,36 @@ interface Props {
const props = defineProps<Props>(); const props = defineProps<Props>();
const open = ref(false); const open = ref(false);
const loading = ref(false);
const q1 = ref(0); const quartiles = computedAsync<HistoryQuartiles | null>(
const median = ref(0); () => open.value && props.id ? getQuartiles(props.id) : null,
const q3 = ref(0); null,
const lineColor = ref(''); loading,
const history = computedAsync(() => getHistory(props.id), []); );
watchEffect(async () => { const lineColor = computed(() => {
if (!open.value || !props.id) { if (!quartiles.value) {
return; return '';
} }
const quartils = getHistoryQuartils(history.value); if (props.buy >= quartiles.value.q3) {
return 'line-blue';
q1.value = quartils.q1;
median.value = quartils.median;
q3.value = quartils.q3;
if (props.buy >= quartils.q3) {
lineColor.value = 'line-blue';
} else if (props.sell >= quartils.q3) {
lineColor.value = 'line-green';
} else {
lineColor.value = '';
} }
}) if (props.sell >= quartiles.value.q3) {
return 'line-green';
}
return '';
});
</script> </script>
<template> <template>
<Tooltip v-model:open="open" class="tooltip"> <Tooltip v-model:open="open" class="tooltip">
<template #header> <template #header>
<LoadingSpinner v-if="history.length < trendingScale" /> <LoadingSpinner v-if="loading || !quartiles" />
<ArrowTrendingUpIcon v-else-if="history[0].average > history[trendingScale - 1].average" /> <MarketTrendIcon v-else :trend="quartiles.trend" />
<ArrowTrendingDownIcon v-else />
</template> </template>
<template #default> <template #default>
<div class="bg-slate-500 -left-1/2 relative tooltip-content" v-if="history.length > 0"> <div class="bg-slate-500 -left-1/2 relative tooltip-content" v-if="quartiles">
<table> <table>
<thead> <thead>
<tr> <tr>
@@ -63,9 +54,9 @@ watchEffect(async () => {
</thead> </thead>
<tbody> <tbody>
<tr :class="lineColor"> <tr :class="lineColor">
<td class="text-right text-nowrap">{{ formatIsk(q1) }}</td> <td class="text-right text-nowrap">{{ formatIsk(quartiles.q1) }}</td>
<td class="text-right text-nowrap">{{ formatIsk(median) }}</td> <td class="text-right text-nowrap">{{ formatIsk(quartiles.median) }}</td>
<td class="text-right text-nowrap">{{ formatIsk(q3) }}</td> <td class="text-right text-nowrap">{{ formatIsk(quartiles.q3) }}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -5,7 +5,7 @@ import {MinusIcon, PlusIcon} from '@heroicons/vue/24/outline';
import {useStorage} from '@vueuse/core'; import {useStorage} from '@vueuse/core';
import {computed, ref} from 'vue'; import {computed, ref} from 'vue';
import {AcquiredType} from './AcquiredType'; import {AcquiredType} from './AcquiredType';
import AcquisitionQuantilsTooltip from './AcquisitionQuantilsTooltip.vue'; import AcquisitionQuartilesTooltip from './AcquisitionQuartilesTooltip.vue';
import {formatEveDate, formatIsk, percentFormater} from "@/formaters.ts"; import {formatEveDate, formatIsk, percentFormater} from "@/formaters.ts";
type Result = { type Result = {
@@ -189,7 +189,7 @@ const total = computed(() => {
<td v-if="showColumn('name')"> <td v-if="showColumn('name')">
<div class="flex"> <div class="flex">
<MarketTypeLabel :id="r.data.type.id" :name="r.data.name" /> <MarketTypeLabel :id="r.data.type.id" :name="r.data.name" />
<AcquisitionQuantilsTooltip :id="r.data.type.id" :buy="r.data.buy" :sell="r.data.sell" /> <AcquisitionQuartilesTooltip :id="r.data.type.id" :buy="r.data.buy" :sell="r.data.sell" />
</div> </div>
</td> </td>
<td v-if="showColumn('buy')" class="text-right">{{ formatIsk(r.data.buy) }}</td> <td v-if="showColumn('buy')" class="text-right">{{ formatIsk(r.data.buy) }}</td>
-59
View File
@@ -1,59 +0,0 @@
import { MarketHistory } from "@/market";
export type HistoryQuartils = {
totalVolume: number,
q1: number,
median: number,
q3: number,
}
export const getHistoryQuartils = (history: MarketHistory[], days?: number): HistoryQuartils => {
const now = Date.now();
const volumes = history
.flatMap(h => {
const volume = h.volume;
if (volume === 0 || (days && new Date(h.date).getTime() < now - days * 24 * 60 * 60 * 1000)) {
return [];
}
const e = estimateVolume(h);
return [[h.highest, e], [h.lowest, volume - e]];
})
.filter(h => h[1] > 0)
.sort((a, b) => a[0] - b[0]);
const totalVolume = volumes.reduce((acc, [_, v]) => acc + v, 0);
const quartilVolume = totalVolume / 4;
const quartils: [number, number, number] = [0, 0, 0];
let currentVolume = 0;
let quartil = 0;
for (const [price, volume] of volumes) {
currentVolume += volume;
if (currentVolume >= quartilVolume * (quartil + 1)) {
quartils[quartil] = price;
if (quartil === 2) {
break;
}
quartil++;
}
}
return {
totalVolume,
q1: quartils[0],
median: quartils[1],
q3: quartils[2],
};
}
const estimateVolume = (history: MarketHistory): number => {
if (history.volume === 0) {
return 0;
}
return Math.max(1, Math.round(history.volume * ((history.average - history.lowest) / (history.highest - history.lowest))));
}
-7
View File
@@ -1,7 +0,0 @@
import { MarketHistoryResponse } from "@/generated/mammon";
import { marketApi } from "@/mammon";
export type MarketHistory = MarketHistoryResponse;
export const getHistory = async (typeId: number): Promise<MarketHistory[]> =>
(await marketApi.findHistory(typeId)).data;
+16
View File
@@ -0,0 +1,16 @@
<script setup lang="ts">
import {type MarketTrend, MarketTrends} from '@/market';
import {ArrowLongRightIcon, ArrowTrendingDownIcon, ArrowTrendingUpIcon} from '@heroicons/vue/24/outline';
interface Props {
trend: MarketTrend;
}
defineProps<Props>();
</script>
<template>
<ArrowTrendingUpIcon v-if="trend === MarketTrends.Up" />
<ArrowTrendingDownIcon v-else-if="trend === MarketTrends.Down" />
<ArrowLongRightIcon v-else />
</template>
+13
View File
@@ -0,0 +1,13 @@
import {
HistoryQuartilesResponse,
HistoryQuartilesResponseTrendEnum,
MarketScanResponseTrendEnum
} from "@/generated/mammon";
import {marketApi} from "@/mammon";
export type HistoryQuartiles = HistoryQuartilesResponse;
export type MarketTrend = MarketScanResponseTrendEnum | HistoryQuartilesResponseTrendEnum;
export const MarketTrends = MarketScanResponseTrendEnum as const;
export const getQuartiles = async (typeId: number, days?: number): Promise<HistoryQuartiles> => (await marketApi.findQuartiles(typeId, days)).data;
+3 -2
View File
@@ -1,2 +1,3 @@
export * from './MarketHistory'; export * from './history.ts';
export * from './HistoryQuartils';
export { default as MarketTrendIcon } from './MarketTrendIcon.vue';