Skip to content

Commit

Permalink
refactor: update data model of IProduct (#40)
Browse files Browse the repository at this point in the history
* update data model of IProduct

* useRuleEffect
  • Loading branch information
zccz14 authored Feb 18, 2024
1 parent 342bbdb commit 88fcac9
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 67 deletions.
26 changes: 13 additions & 13 deletions @libs/utils/getClosePriceByDesiredProfit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
* @param currency - 账户货币
* @param quotes - 市场报价
* @returns - 目标平仓价
* @see https://tradelife.feishu.cn/wiki/wikcnRNzWSF7jtkH8nGruaMhhlh
*/
export const getClosePriceByDesiredProfit = (
product: IProduct,
Expand All @@ -22,23 +21,24 @@ export const getClosePriceByDesiredProfit = (
) => {
const variant_coefficient = variant === PositionVariant.LONG ? 1 : -1;
const cross_product_exchange_rate =
product.base_currency !== currency
product.quote_currency !== currency
? (variant === PositionVariant.LONG
? quotes(`${product.base_currency}${currency}`)?.bid
: quotes(`${product.base_currency}${currency}`)?.ask) ?? 1
? quotes(`${product.quote_currency}${currency}`)?.bid
: quotes(`${product.quote_currency}${currency}`)?.ask) ?? 1
: 1;

const beta =
desiredProfit / (variant_coefficient * volume * (product.value_speed ?? 1));
desiredProfit /
(variant_coefficient *
volume *
(product.value_scale ?? 1) *
(product.value_scale_unit ? 1 / openPrice : 1));

if (!product.is_underlying_base_currency) {
return openPrice + beta / cross_product_exchange_rate;
if (product.quote_currency === currency) {
return beta + openPrice;
}
if (product.quoted_currency === currency) {
return openPrice + beta;
if (product.base_currency && product.base_currency === currency) {
return openPrice / (1 - beta);
}
if (beta >= cross_product_exchange_rate) {
return NaN;
}
return openPrice / (1 - beta / cross_product_exchange_rate);
return openPrice + beta / cross_product_exchange_rate;
};
35 changes: 20 additions & 15 deletions @models/double-ma.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
// 双均线策略 (Double Moving Average)
// 当短期均线由下向上穿越长期均线时做多 (金叉)
// 当短期均线由上向下穿越长期均线时做空 (死叉)
import { useParamOHLC, useSMA, useSimplePositionManager } from "@libs";
import {
useParamOHLC,
useRuleEffect,
useSMA,
useSimplePositionManager,
} from "@libs";

export default () => {
// 使用收盘价序列
const { product_id, close } = useParamOHLC("SomeKey");
// NOTE: 使用当前 K 线的上一根 K 线的收盘价,保证策略在 K 线结束时才会执行
const idx = close.length - 2;
const { product_id, close } = useParamOHLC("品种");

// 使用 20,60 均线
const sma20 = useSMA(close, 20);
Expand All @@ -21,15 +24,17 @@ export default () => {
product_id
);

useEffect(() => {
if (idx < 60) return; // 略过一开始不成熟的均线数据
// 金叉开多平空
if (sma20[idx] > sma60[idx]) {
setTargetVolume(1);
}
// 死叉开空平多
if (sma20[idx] < sma60[idx]) {
setTargetVolume(-1);
}
}, [idx]);
useRuleEffect(
"均线金叉做多",
() => sma20.previousValue > sma60.previousValue,
() => setTargetVolume(1),
[close.currentIndex]
);

useRuleEffect(
"均线死叉做空",
() => sma20.previousValue < sma60.previousValue,
() => setTargetVolume(-1),
[close.currentIndex]
);
};
9 changes: 5 additions & 4 deletions @models/shannon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ export default () => {
const datasource_id = useParamString("DataSource", "Y");
const product_id = useParamString("Product");
const period = useParamString("Period", "PT1H");
const currency = useParamString("Currency", "USD");
// Get the product information and price data
const product = useProduct(datasource_id, product_id);
const { close } = useOHLC(datasource_id, product_id, period);
// More parameters
const initial_balance = useParamNumber("Initial Balance", 100_000);
const threshold = useParamNumber("Threshold", 1);
// Get the account information
const accountInfo = useAccountInfo();
const accountInfo = useAccountInfo({ currency });
// Use a simple position manager
const [actualVolume, setVolume] = useSimplePositionManager(
accountInfo.account_id,
Expand All @@ -33,9 +34,9 @@ export default () => {
const totalValueToHold = totalValue * 0.5;
// infer the volume to hold
const valuePerVolume =
price *
(product.value_speed ?? 1) *
(product.is_underlying_base_currency ? -1 / price : 1);
(product.value_scale ?? 1) *
(product.value_scale_unit ? 1 : price) *
(product.quote_currency === accountInfo.money.currency ? 1 : -1 / price);
const expectedVolume = totalValueToHold / valuePerVolume;
// calculate the error rate
const volume_step = product.volume_step ?? 1;
Expand Down
59 changes: 24 additions & 35 deletions global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,54 +293,39 @@ declare interface IAccountInfo {
}

/**
* Product: Subject Matter of trading
*
* @public
* Product: The underlying asset of a transaction.
*/
declare interface IProduct {
/** Data source ID */
datasource_id: string;
/** Product ID */
product_id: string;
/** Readable product name */
name?: string;

/**
* Base Currency
*
* The base currency is the currency used as the basis for exchange rate quotes, expressed as the number of units of the currency that can be exchanged for one unit of the quoted currency.
* Product ID
*
* e.g. The base currency of GBPJPY is GBP; the base currency of USDCAD is USD.
* e.g. GBPJPY 的 base_currency 为 GBP; USDCAD 的 base_currency 为 USD.
* It's RECOMMENDED that make the product ID the original form from the data source. Don't transform it to somehow standard form.
*/
base_currency: string;

product_id: string;
/** Human-readable product name */
name?: string;
/**
* Quoted Currency
*
* The quoted currency is the currency being used as the reference for the exchange rate quote, expressed as the number of units of the quoted currency that can be exchanged for one unit of the base currency.
* The quote currency to price the product.
*
* e.g. The quoted currency of GBPJPY is JPY; the quoted currency of USDCAD is CAD.
* e.g. GBPJPY 的 quoted_currency 为 JPY; USDCAD 的 quoted_currency 为 CAD.
*
* For non-forex products, the quoted currency should be empty.
* e.g. "USD", "CNY", "GBP", "USDT", "BTC", ...etc.
*/
quoted_currency?: string;
quote_currency?: string;

/**
* Is the underlying asset the base currency?
* Base Currency
*
* One lot corresponds to the quantity of the underlying asset specified by value_speed, which can be the base currency or other commodities.
* Only available in foreign exchange products.
*
* - For commodities, including spot and futures, this value is usually false, because one lot corresponds to a multiple of value_speed of the commodity quantity.
* If defined, the price of this product (P(this, quote_currency)) can be treated as P(base_currency, quote_currency)
*
* - For forex, this value is usually true, because one lot corresponds to a multiple of value_speed of the equivalent of the base currency in any currency.
* The base currency is the currency used as the basis for exchange rate quotes, expressed as the number of units of the currency that can be exchanged for one unit of the quoted currency.
*
* If the value is empty, it is semantically equivalent to false.
* e.g. The base currency of GBPJPY is GBP; the base currency of USDCAD is USD.
*
* If this value is true, an additional division by the "closing price" of this product is required in the standard yield formula.
*/
is_underlying_base_currency?: boolean;
base_currency?: string;

/**
* price step, default is 1
Expand All @@ -351,18 +336,22 @@ declare interface IProduct {
*/
volume_step?: number;
/**
* Value speed, default is 1
* Value scale, default is 1
*
* The quantity of the underlying asset specified by one lot.
*/
value_scale?: number;

/**
* Unit of value scale.
*
* ~~For every 1 lot increase in price, the settlement asset income obtained~~
* - Leave empty to use the product itself.
* - If the value is equal to currency, it means that the 1 volume is based on the currency.
*/
value_speed?: number;
value_scale_unit?: string;

/**
* Margin rate
*
* Margin calculation reference [How to calculate margin](https://tradelife.feishu.cn/wiki/wikcnEVBM0RQ7pmbNZUxMV8viRg)
*/
margin_rate?: number;

Expand Down

0 comments on commit 88fcac9

Please sign in to comment.