Après avoir réalisé la conception d'une stratégie de trading quantitative, comment pouvez-vous connaître la situation de base de votre stratégie, telle que la logique de la stratégie et la direction des rendements de la stratégie? Bien sûr, nous ne pouvons pas utiliser de l'argent réel directement pour exécuter la stratégie sur le marché de trading réel, mais nous pouvons utiliser des données historiques pour tester votre stratégie et connaître les profits de votre stratégie dans les données historiques.
FMZ Quant Trading Platform divise le système de backtest enniveau de botetniveau de simulation. Le niveau de bot est de backtest complètement selon les données historiques complètes; tandis que le niveau de simulation backtest génèretick
les données sont basées sur les données historiques réelles, mais les données au niveau du bot sont plus précises et les résultats sont plus crédibles. Cependant, le backtesting n'est que la performance de la stratégie selon les données historiques. Les données historiques ne peuvent pas représenter pleinement le marché futur. Le marché historique peut se répéter, ou cela peut également conduire au cygne noir. Par conséquent, les résultats du backtest doivent être traités de manière rationnelle et objective.
Leniveau de simulation Tickgénère la simulationDonnées de tiquesLes résultats de l'expérience sont basés sur la période de la ligne K sous-jacente, chaque période de la ligne K sous-jacente générera un maximum de 12 points de temps de backtest.Niveau du marché réelLe mécanisme de backtesting de FMZ Quant permet à la stratégie de négocier plusieurs fois sur une seule ligne K, évitant la situation où la négociation ne peut être exécutée qu'au prix de clôture.
Description du mécanisme du système de backtesting
Tick de niveau de simulation Leniveau de simulation Tickest basé sur les données de ligne K sous-jacentes du système de backtest, simulant les données de tick pour backtest dans le cadre des valeurs du prix le plus élevé, le prix le plus bas, le prix d'ouverture et le prix de clôture d'une barre de ligne K sous-jacente donnée selon un certain algorithme.Description du mécanisme de simulation au niveau du système de backtesting.
Tick au niveau du robot
Le backtest de niveau de bot est les données réelles de niveau de tick dans la série de temps Bar. Pour les stratégies basées sur les données de niveau de tick, l'utilisation du niveau réel du marché pour le backtest est plus proche de la réalité. Dans le backtest de niveau de bot, les données de tick sont des données enregistrées réelles, pas simulées. Il prend en charge les données de profondeur, la lecture des données d'enregistrement des transactions sur le marché, la profondeur personnalisée et chaque donnée de trading individuelle. La taille maximale du backtest de données de niveau de marché réel est jusqu'à un maximum de 50 Mo, sans limite sur la plage de temps de backtest dans la limite supérieure de l'ensemble de données. Si vous avez besoin d'élargir la plage de temps de backtest autant que possible, vous pouvez réduire la valeur du réglage de la profondeur d'équipement et ne pas utiliser chaque donnée de trading individuelle pour augmenter la plage de temps de backtest Call.GetDepth
, GetTrades
Dans un moment de données de marché sur la chronologie, appelantGetTicker
, GetTrades
, GetDepth
etGetRecords
Ne pas pousser le temps plusieurs fois lorsque le temps se déplace sur la chronologie du backtest (ce qui ne déclenchera pas un saut vers le prochain moment des données du marché). Les appels répétés à l'une des fonctions ci-dessus pousseront le temps du backtest pour se déplacer sur la chronologie du backtest (sauter vers le prochain moment des données du marché). Lorsque le niveau réel du marché est utilisé pour le backtest, il n'est pas recommandé de choisir un moment antérieur. Il peut ne pas y avoir de données au niveau du marché réel dans la période de temps prématurée.
Tick au niveau du robotetTick au niveau de la simulationLes modes de négociation sont les suivants: le mécanisme de correspondance des transactions du système de backtest: la correspondance des transactions d'ordre est effectuée en fonction du prix observé et le volume total est négocié.
Le système de backtesting prend en charge les stratégies de backtesting écrites et conçues par:JavaScript
, TypeScript
, Python
, C++
, PINE
, MyLanguage
, Blockly
visualisation.
Le backtest deJavaScriptetC++Les stratégies de trading est menée dans le navigateur, et le vrai marché bot ouNous avons une application.Le marché réel de change émulé (c'est-à-dire leNous avons une application.L'échange émulé de la plateforme de trading FMZ Quant) s'exécute sans installer aucun autre logiciel, bibliothèques ou modules.
Le backtest dePythonL'opération de marché réelle et le backtest dépendent tous deux de la capacité de l'utilisateur à effectuer des tests sur les marchés.PythonSi certaines bibliothèques sont nécessaires, elles doivent être installées manuellement (uniquement les bibliothèques communes)Pythonles bibliothèques sont prises en charge sur les serveurs publics FMZ Quant).
Il soutientJavaScriptle débogage des stratégies de backtesting dans Chrome DevTools,Veuillez vous référer à.
La fonction d'optimisation des paramètres du système de backtest de la plateforme de trading quantique FMZ consiste à définir les combinaisons de paramètres selon chaque option d'optimisation des paramètres pendant le backtest.Optimisationoption située sur le côté droit du paramètre de stratégie pour afficher les paramètres d'optimisation.
JavaScript
, PINE
, etMy Language
, et ne prend pas en charge l'optimisation des paramètres sur les modèles.Les combinaisons de paramètres sont générées sur la base deminimum
, maximum
, etstep size
Le système de backtesting itère à travers ces combinaisons de paramètres pour le backtesting (c'est-à-dire, backtesting chaque combinaison de paramètres une fois).NuméroLe système de backtesting permet d'optimiser le type de données.
Dans lepage d'édition de stratégie, dans la pagination de
backtest
(enregistré dans le code de stratégie via le bouton backtest
dans le domaine de l'édition de la stratégie./*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
'''backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
'''
/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
Cliquez sur JavaScript
/Python
/C++
/MyLanguage
/PINE
langues lors de l'enregistrement des paramètres de backtest dans le code de stratégie:
Mon langage:
(*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*)
Langue PINE:
/*backtest
start: 2021-06-26 00:00:00
end: 2021-09-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
Le système de backtesting de la plateforme de trading quantitatif FMZ prend en charge les sources de données personnalisées, le système de backtesting utilise lesGET
méthode pour demander une URL personnalisée (URL accessible au public) afin d'obtenir une source de données externe pour le backtest.
Paramètre | Signification | Expliquer |
---|---|---|
le symbole | Nom du symbole | Données du marché au comptant, telles que:BTC_USDT , les données du marché à terme, telles que:BTC_USDT.swap , données sur les taux de financement des contrats perpétuels à terme, telles que:BTC_USDT.funding , les données relatives à l'indice des prix des contrats à terme perpétuels, telles que:BTC_USDT.index |
- Je vous en prie. | Les échanges | Les éléments suivants doivent être pris en considération: |
ronde | La précision des données | True signifie que la précision spécifique est définie dans les données transmises par la source de données personnalisée.round=true |
période | Période de données en ligne K (millièmes de seconde) | par exemple:60000 est une période de 1 minute |
profondeur | Niveaux de profondeur | 1-20 |
commerces | Si les données doivent être scindées | vrai (1) / faux (2) |
de | Heure de début | Le timestamp est unix |
à | Le temps de la fin | Le timestamp est unix |
détails | Données demandées pour les détails du symbole | True signifie qu'il doit être fourni par une source de données personnalisée.detail=true |
personnalisation | – | Ce paramètre peut être ignoré. |
Lorsque la source de données des objets d'échange au comptant et des objets d'échange à terme est définie sur une source de données personnalisée (feeder), le système de backtesting envoie une demande au service de source de données personnalisée:
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Bitget&from=1351641600&period=86400000&round=true&symbol=BTC_USDT&to=1611244800&trades=1
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_OKX&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.swap&to=1611244800&trades=1
Le format retourné doit être l'un des deux formats suivants (qui seront automatiquement reconnues par le système):
Niveau de simulation Tick, voici un exemple de données JSON:
{
"detail": {
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10
},
"schema":["time", "open", "high", "low", "close", "vol"],
"data":[
[1564315200000, 9531300, 9531300, 9497060, 9497060, 787],
[1564316100000, 9495160, 9495160, 9474260, 9489460, 338]
]
}
Cochez le niveau de bot, voici un exemple de données JSON:
Les données de backtest au niveau du tick (contiennent des informations sur la profondeur du marché, et le format de profondeur est un tableau de[price, volume]
Il peut avoir plusieurs niveaux de profondeur,asks
pour l'ordre croissant des prix,bids
pour l' ordre décroissant des prix).
{
"detail": {
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10
},
"schema":["time", "asks", "bids", "trades", "close", "vol"],
"data":[
[1564315200000, [[9531300, 10]], [[9531300, 10]], [[1564315200000, 0, 9531300, 10]], 9497060, 787],
[1564316100000, [[9531300, 10]], [[9531300, 10]], [[1564316100000, 0, 9531300, 10]], 9497060, 787]
]
}
Le champ | Définition |
---|---|
détails | Informations détaillées sur le type de données demandé, |
le nom de la monnaie libellée, le nom de la la précision, la quantité de commande minimale, etc. Il spécifie les attributs des colonnes dans les données array, qui est sensible aux petites lettres et est limité au temps, ouvert, haut, bas, fermé, vol, demande, offre, négocie Les données La structure des colonnes, les données enregistrées selon le schéma réglages.
champ de détail
Le champ | Définition |
---|---|
- Je vous en prie. | Exchange Id, veuillez noter que le spot et les contrats à terme d'un |
Certains échanges ont des effets différents. | |
le symbole | Code du produit de négociation |
alias | Le symbole de l'échange correspondant au courant |
code du produit commercial | |
Monnaie de base | Monnaie de négociation |
CitéMonnaie | Monnaies libellées |
MargeMonnaie | Monnaie de marge |
basePrécision | Vérité de la monnaie de la transaction |
Citation précise | Précision de la devise de prix |
MinQty | Quantité minimale de commande |
Le nombre maximal | Quantité maximale de commande |
Le projet de | Montant minimum de la commande |
maxNotif | Montant maximal de la commande |
prixTick | Saut de prix |
Le volume | Valeur minimale de modification de la quantité d'ordre (un saut dans la quantité) |
quantité de commande) | |
MargeLe niveau | Valeur de l'effet de levier des contrats à terme |
type de contrat | Pour les contrats perpétuels fixés à:swap , le |
Le système de backtest continuera à envoyer des indices de taux de financement et de prix Les demandes.
Attributs de colonne spéciauxasks
, bids
, trades
:
Le champ | Définition | Les commentaires |
---|---|---|
demande / offre | [prix, volume],...] | Par exemple, les données |
LeLive Trading Level Tick
Exemple de données:[[9531300, 10]]
Je ne sais pas.
Les échanges, le temps, la direction, le prix, le volume...
Par exemple, les donnéesLive Trading Level Tick
Exemple de données:[[1564315200000, 0, 9531300, 10]]
|
Lors du backtesting des contrats perpétuels sur les bourses à terme, les
Les sources de données nécessitent également des données supplémentaires sur le taux de financement et le prix
Le système de backtesting continuera d'envoyer des requêtes
pour les taux de financement uniquement lorsque les données de marché demandées sont renvoyées
et le champ de détail dans la structure retournée contient le"contractType": "swap"
une paire clé-valeur.
Lorsque le système de backtesting reçoit des données sur le taux de financement, il continuer d'envoyer des demandes de données sur l'indice des prix.
La structure des données sur le taux de financement est la suivante:
{
"detail": {
"eid": "Futures_Binance",
"symbol": "BTC_USDT.funding",
"alias": "BTC_USDT.funding",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "",
"basePrecision": 8,
"quotePrecision": 8,
"minQty": 1,
"maxQty": 10000,
"minNotional": 1,
"maxNotional": 100000000,
"priceTick": 1e-8,
"volumeTick": 1e-8,
"marginLevel": 10
},
"schema": [
"time",
"open",
"high",
"low",
"close",
"vol"
],
"data": [
[
1584921600000,
-16795,
-16795,
-16795,
-16795,
0
],
[
1584950400000,
-16294,
-16294,
-16294,
-16294,
0
]
// ...
]
}
Exemple de demande de données sur le taux de financement à partir du backtesting Le système est le suivant:
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.funding&to=1611244800&trades=0
La structure des données relatives à l'indice des prix est la suivante:
{
"detail": {
"eid": "Futures_Binance",
"symbol": "BTC_USDT.index",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"contractType": "index",
"marginCurrency": "USDT",
"basePrecision": 3,
"quotePrecision": 1,
"minQty": 0.001,
"maxQty": 1000,
"minNotional": 0,
"maxNotional": 1.7976931348623157e+308,
"priceTick": 0.1,
"volumeTick": 0.001,
"marginLevel": 10,
"volumeMultiple": 1
},
"schema": [
"time",
"open",
"high",
"low",
"close",
"vol"
],
"data": [
[1584921600000, 58172, 59167, 56902, 58962, 0],
[1584922500000, 58975, 59428, 58581, 59154, 0],
// ...
]
}
Exemple de demande de données sur l'indice des prix envoyée par le backtesting Le système est le suivant:
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.index&to=1611244800&trades=0
Indiquer l'adresse de la source de données, par exemple:http://120.24.2.20:9090/data
Le programme de service de source de données personnalisé est écrit en utilisantGolang
:
package main
import (
"fmt"
"net/http"
"encoding/json"
)
func Handle (w http.ResponseWriter, r *http.Request) {
// e.g. set on backtest DataSourse: http://xxx.xx.x.xx:9090/data
// request: GET http://xxx.xx.x.xx:9090/data?custom=0&depth=20&detail=true&eid=OKX&from=1584921600&period=86400000&round=true&symbol=BTC_USDT&to=1611244800&trades=1
// http://xxx.xx.x.xx:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1599958800&period=3600000&round=true&symbol=BTC_USDT.swap&to=1611244800&trades=0
fmt.Println("request:", r)
// response
defer func() {
// response data
/* e.g. data
{
"detail": {
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10
},
"schema": [
"time",
"open",
"high",
"low",
"close",
"vol"
],
"data": [
[1610755200000, 3673743, 3795000, 3535780, 3599498, 8634843151],
[1610841600000, 3599498, 3685250, 3385000, 3582861, 8015772738],
[1610928000000, 3582499, 3746983, 3480000, 3663127, 7069811875],
[1611014400000, 3662246, 3785000, 3584406, 3589149, 7961130777],
[1611100800000, 3590194, 3641531, 3340000, 3546823, 8936842292],
[1611187200000, 3546823, 3560000, 3007100, 3085013, 13500407666],
[1611273600000, 3085199, 3382653, 2885000, 3294517, 14297168405],
[1611360000000, 3295000, 3345600, 3139016, 3207800, 6459528768],
[1611446400000, 3207800, 3307100, 3090000, 3225990, 5797803797],
[1611532800000, 3225945, 3487500, 3191000, 3225420, 8849922692]
]
}
*/
// /* Simulation level Tick
ret := map[string]interface{}{
"detail": map[string]interface{}{
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10,
},
"schema": []string{"time","open","high","low","close","vol"},
"data": []interface{}{
[]int64{1610755200000, 3673743, 3795000, 3535780, 3599498, 8634843151}, // 1610755200000 : 2021-01-16 08:00:00
[]int64{1610841600000, 3599498, 3685250, 3385000, 3582861, 8015772738}, // 1610841600000 : 2021-01-17 08:00:00
[]int64{1610928000000, 3582499, 3746983, 3480000, 3663127, 7069811875},
[]int64{1611014400000, 3662246, 3785000, 3584406, 3589149, 7961130777},
[]int64{1611100800000, 3590194, 3641531, 3340000, 3546823, 8936842292},
[]int64{1611187200000, 3546823, 3560000, 3007100, 3085013, 13500407666},
[]int64{1611273600000, 3085199, 3382653, 2885000, 3294517, 14297168405},
[]int64{1611360000000, 3295000, 3345600, 3139016, 3207800, 6459528768},
[]int64{1611446400000, 3207800, 3307100, 3090000, 3225990, 5797803797},
[]int64{1611532800000, 3225945, 3487500, 3191000, 3225420, 8849922692},
},
}
// */
/* Bot level Tick
ret := map[string]interface{}{
"detail": map[string]interface{}{
"eid": "Binance",
"symbol": "BTC_USDT",
"alias": "BTCUSDT",
"baseCurrency": "BTC",
"quoteCurrency": "USDT",
"marginCurrency": "USDT",
"basePrecision": 5,
"quotePrecision": 2,
"minQty": 0.00001,
"maxQty": 9000,
"minNotional": 5,
"maxNotional": 9000000,
"priceTick": 0.01,
"volumeTick": 0.00001,
"marginLevel": 10,
},
"schema": []string{"time", "asks", "bids", "trades", "close", "vol"},
"data": []interface{}{
[]interface{}{1610755200000, []interface{}{[]int64{9531300, 10}}, []interface{}{[]int64{9531300, 10}}, []interface{}{[]int64{1610755200000, 0, 9531300, 10}}, 9497060, 787},
[]interface{}{1610841600000, []interface{}{[]int64{9531300, 15}}, []interface{}{[]int64{9531300, 15}}, []interface{}{[]int64{1610841600000, 0, 9531300, 11}}, 9497061, 789},
},
}
*/
b, _ := json.Marshal(ret)
w.Write(b)
}()
}
func main () {
fmt.Println("listen http://localhost:9090")
http.HandleFunc("/data", Handle)
http.ListenAndServe(":9090", nil)
}
stratégie de test,JavaScript
Exemple:
/*backtest
start: 2021-01-16 08:00:00
end: 2021-01-22 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"OKX","currency":"BTC_USDT","feeder":"http://120.24.2.20:9090/data"}]
args: [["number",2]]
*/
function main() {
var ticker = exchange.GetTicker()
var records = exchange.GetRecords()
Log(exchange.GetName(), exchange.GetCurrency())
Log(ticker)
Log(records)
}
FMZ Quant Trading Platform est open-source pour leJavaScript
La langue et lePython
langage du moteur de backtest local, prenant en charge le réglage de la période sous-jacente de la ligne K pendant le backtest.
Touche de raccourci pour basculer entre la stratégie Ctrl +,
pour revenir à la page Ctrl
Appuie sur la touche.,
.
Touche de raccourci pour la stratégie d'économie
Utilisez la clé.Ctrl + s
pour sauver des stratégies.
Raccourci pour démarrer le backtest de stratégie
Utilisez la clé.Ctrl + b
pour activer
Le code source de l'algorithme Sharpe dans le système de backtesting:
function returnAnalyze(totalAssets, profits, ts, te, period, yearDays) {
// force by days
period = 86400000
if (profits.length == 0) {
return null
}
var freeProfit = 0.03 // 0.04
var yearRange = yearDays * 86400000
var totalReturns = profits[profits.length - 1][1] / totalAssets
var annualizedReturns = (totalReturns * yearRange) / (te - ts)
// MaxDrawDown
var maxDrawdown = 0
var maxAssets = totalAssets
var maxAssetsTime = 0
var maxDrawdownTime = 0
var maxDrawdownStartTime = 0
var winningRate = 0
var winningResult = 0
for (var i = 0; i < profits.length; i++) {
if (i == 0) {
if (profits[i][1] > 0) {
winningResult++
}
} else {
if (profits[i][1] > profits[i - 1][1]) {
winningResult++
}
}
if ((profits[i][1] + totalAssets) > maxAssets) {
maxAssets = profits[i][1] + totalAssets
maxAssetsTime = profits[i][0]
}
if (maxAssets > 0) {
var drawDown = 1 - (profits[i][1] + totalAssets) / maxAssets
if (drawDown > maxDrawdown) {
maxDrawdown = drawDown
maxDrawdownTime = profits[i][0]
maxDrawdownStartTime = maxAssetsTime
}
}
}
if (profits.length > 0) {
winningRate = winningResult / profits.length
}
// trim profits
var i = 0
var datas = []
var sum = 0
var preProfit = 0
var perRatio = 0
var rangeEnd = te
if ((te - ts) % period > 0) {
rangeEnd = (parseInt(te / period) + 1) * period
}
for (var n = ts; n < rangeEnd; n += period) {
var dayProfit = 0.0
var cut = n + period
while (i < profits.length && profits[i][0] < cut) {
dayProfit += (profits[i][1] - preProfit)
preProfit = profits[i][1]
i++
}
perRatio = ((dayProfit / totalAssets) * yearRange) / period
sum += perRatio
datas.push(perRatio)
}
var sharpeRatio = 0
var volatility = 0
if (datas.length > 0) {
var avg = sum / datas.length;
var std = 0;
for (i = 0; i < datas.length; i++) {
std += Math.pow(datas[i] - avg, 2);
}
volatility = Math.sqrt(std / datas.length);
if (volatility !== 0) {
sharpeRatio = (annualizedReturns - freeProfit) / volatility
}
}
return {
totalAssets: totalAssets,
yearDays: yearDays,
totalReturns: totalReturns,
annualizedReturns: annualizedReturns,
sharpeRatio: sharpeRatio,
volatility: volatility,
maxDrawdown: maxDrawdown,
maxDrawdownTime: maxDrawdownTime,
maxAssetsTime: maxAssetsTime,
maxDrawdownStartTime: maxDrawdownStartTime,
winningRate: winningRate
}
}
Éditeur de stratégie
Fonctions d'entrée de stratégie