MQL4 WebRequest POST Json 到 Django API 使用 Django rest 框架,在主体末尾获取 \x00
MQL4 WebRequest POST Json to Django API using Django rest framework, getting \x00 at the end of body
我只用了几个星期的 Django,所以可能会有一些错误。
我有一个使用 Django rest 框架的 API,它似乎运行良好。
使用 postman 一切正常
我使用 Mql4 中的 WebRequest 将数据发送到 api
string data = "{ ... }“;
char post_data[];
post_data = StringToCharArray(data, post_data, WHOLE_ARRAY);
int r = WebRequest("POST", "http://127.0.0.1/api/symbol/","Content-Type: application/json",5000, data,res_data, res_headers);
给WebRequest的数据没问题,但是函数在body的末尾添加了\x00。
这是我的 post 到达 Django 休息框架时的数据
{'Content-Length': '982', 'Content-Type': 'application/json', 'Accept': 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*', 'Host': '127.0.0.1', 'Accept-Language': 'fr,en', 'Accept-Charset': '*,utf-8', 'Connection': 'Keep-Alive', 'Proxy-Connection': 'Keep-Alive', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache', 'User-Agent': 'MetaTrader 4 Terminal/4.1353 (Windows NT 6.1; x86)'}
b'{"name": "GOLDs","date_market": "2022-02-01T00:00:00.000000Z","period": "M1","open_price": 1797.64,"close_price": 1870.91,"low_price": 1788.33,"high_price": 1879.12,"bollinger_band":[{"period":"M1","moving_average_period":20,"standard_deviation":1.5,"high":1936.06829,"low":1717.61271,"moving_average":1826.8405},{"period":"M1","moving_average_period":20,"standard_deviation":2,"high":1972.47755,"low":1681.20345,"moving_average":1826.8405},{"period":"M1","moving_average_period":20,"standard_deviation":2.5,"high":2008.88681,"low":1644.79419,"moving_average":1826.8405}],"moving_average":[{"period":"M1","moving_average_period":50,"type": "0","value":1569.6854},{"period":"M1","moving_average_period":100,"type": "0","value":1399.8002},{"period":"M1","moving_average_period":200,"type": "0","value":1245.38985}],"MACD_zerolag":[{"period":"M1","fast_EMA_period":12,"slow_EMA_period":26,"signal_EMA_period":9,"histogram_value":-0.01794,"signal_value":0.09465,"MACD_value":0.07671}]}\x00'
所以我得到以下错误:
POST /api/symbol/ - 400
{'Content-Type': 'application/json', 'Vary': 'Accept', 'Allow': 'GET, POST, HEAD, OPTIONS'}
b'{"detail":"JSON parse error - Extra data: line 1 column 982 (char 981)"}'
如果使用 Postman 发送相同的数据删除 \x00 一切顺利。
mql4 客户端配置错误吗?
或者我可以删除接收到的数据来删除这个 \x00 吗?
这是我的 models.py
from django.db import models, transaction
M1 = 'M1'
M5 = 'M5'
M15 = 'M15'
M30 = 'M30'
H1 = 'H1'
H4 = 'H4'
DAILY = 'DAILY'
WEEKLY = 'WEEKLY'
MONTHLY = 'MONTHLY'
PERIOD_CHOICES = (
(M1, 'Une minute'),
(M5, 'Cinq minutes'),
(M15, 'Quinze minutes'),
(M30, 'Trente minutes'),
(H1, 'Une heure'),
(H4, 'Quatre heures'),
(DAILY, 'Journalier'),
(WEEKLY, 'Hebdomadaire'),
(MONTHLY, 'Mensuel'),
)
class BollingerBand(models.Model):
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
moving_average_period = models.CharField(max_length=8)
standard_deviation = models.DecimalField(max_digits=6, decimal_places=2)
symbol = models.ForeignKey('API.Symbol', on_delete=models.CASCADE, related_name='bollinger_band', default=1)
high = models.DecimalField(max_digits=12, decimal_places=6)
low = models.DecimalField(max_digits=12, decimal_places=6)
moving_average = models.DecimalField(max_digits=12, decimal_places=6)
class MovingAverage(models.Model):
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
moving_average_period = models.CharField(max_length=8)
type = models.TextField(max_length=30)
symbol = models.ForeignKey('API.Symbol', on_delete=models.CASCADE, related_name='moving_average', default=1)
value = models.DecimalField(max_digits=12, decimal_places=6)
class MACDZR(models.Model):
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
fast_EMA_period = models.CharField(max_length=4)
slow_EMA_period = models.CharField(max_length=4)
signal_EMA_period = models.CharField(max_length=4)
symbol = models.ForeignKey('API.Symbol', on_delete=models.CASCADE, related_name='MACD_zerolag', default=1)
histogram_value = models.DecimalField(max_digits=12, decimal_places=6)
signal_value = models.DecimalField(max_digits=12, decimal_places=6)
MACD_value = models.DecimalField(max_digits=12, decimal_places=6)
class Symbol(models.Model):
name = models.CharField(max_length=30, default='undefined')
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
date_market = models.DateTimeField()
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
open_price = models.DecimalField(max_digits=12, decimal_places=6)
close_price = models.DecimalField(max_digits=12, decimal_places=6)
high_price = models.DecimalField(max_digits=12, decimal_places=6)
low_price = models.DecimalField(max_digits=12, decimal_places=6)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['name', 'date_market', 'period'],
name='unique_symbol'
)
]
def __str__(self):
return self.name
Serializers.py
from rest_framework import serializers
from API.models import Symbol, BollingerBand, MACDZR, MovingAverage
class BollingerBandSerializer(serializers.ModelSerializer):
class Meta:
model = BollingerBand
fields = ['period',
'moving_average_period',
'standard_deviation',
'symbol',
'high',
'low',
'moving_average']
class MovingAverageSerializer(serializers.ModelSerializer):
class Meta:
model = MovingAverage
fields = ['period',
'moving_average_period',
'type',
'symbol',
'value']
class MACDZRSerializer(serializers.ModelSerializer):
class Meta:
model = MACDZR
fields = ['period',
'fast_EMA_period',
'slow_EMA_period',
'signal_EMA_period',
'symbol',
'histogram_value',
'signal_value',
'MACD_value']
class SymbolSerializer(serializers.ModelSerializer):
bollinger_band = BollingerBandSerializer(many=True)
moving_average = MovingAverageSerializer(many=True)
MACD_zerolag = MACDZRSerializer(many=True)
class Meta:
model = Symbol
fields = ['id',
'name',
'date_created',
'date_updated',
'date_market',
'period',
'open_price',
'close_price',
'high_price',
'low_price',
'bollinger_band',
'moving_average',
'MACD_zerolag'
]
def create(self, validated_data):
bollinger_bands_data = validated_data.pop('bollinger_band')
moving_averages_data = validated_data.pop('moving_average')
MACDs_zerolag_data = validated_data.pop('MACD_zerolag')
symbol = Symbol.objects.create(**validated_data)
for bollinger_band_data in bollinger_bands_data:
BollingerBand.objects.create(symbol=symbol, **bollinger_band_data)
for MACD_zerolag_data in MACDs_zerolag_data:
MACDZR.objects.create(symbol=symbol, **MACD_zerolag_data)
for moving_average_data in moving_averages_data:
MovingAverage.objects.create(symbol=symbol, **moving_average_data)
return symbol
和settings.py
"""
Django settings for trading_project project.
Generated by 'django-admin startproject' using Django 4.0.2.
For more information on this file, see
https://docs.djangoproject.com/en/4.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-)6f&ci7@)t96(k^7am%66@%e%(88a%u00+3h5a13s461#q7dqm'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = [
'0.0.0.0',
'127.0.0.1',
]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#'django.contrib.sites',
'rest_framework',
'authentication',
'API',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'request_logging.middleware.LoggingMiddleware',
]
ROOT_URLCONF = 'trading_project.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates/'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'trading_project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'trading_project',
'USER': 'admin',
'PASSWORD': 'testpassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
LANGUAGE_CODE = 'fr-fr'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
AUTH_USER_MODEL = 'authentication.User'
LOGIN_URL = 'login'
LOGIN_REDIRECT_URL = 'home'
LOGOUT_URL = 'logout'
LOGOUT_REDIRECT_URL = 'login'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.request': {
'handlers': ['console'],
'level': 'DEBUG', # change debug level as appropiate
'propagate': False,
},
},
}
如果有人对此有简单的解决方案
谢谢
我找到了我的解决方案,
当我将数据字符串转换为 post_Data 对象时,长度不是 WHOLE_ARRAY,而是 StringLen.
StringToCharArray(data, post_data,0, StringLen(data));
我只用了几个星期的 Django,所以可能会有一些错误。
我有一个使用 Django rest 框架的 API,它似乎运行良好。 使用 postman 一切正常
我使用 Mql4 中的 WebRequest 将数据发送到 api
string data = "{ ... }“;
char post_data[];
post_data = StringToCharArray(data, post_data, WHOLE_ARRAY);
int r = WebRequest("POST", "http://127.0.0.1/api/symbol/","Content-Type: application/json",5000, data,res_data, res_headers);
给WebRequest的数据没问题,但是函数在body的末尾添加了\x00。
这是我的 post 到达 Django 休息框架时的数据
{'Content-Length': '982', 'Content-Type': 'application/json', 'Accept': 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*', 'Host': '127.0.0.1', 'Accept-Language': 'fr,en', 'Accept-Charset': '*,utf-8', 'Connection': 'Keep-Alive', 'Proxy-Connection': 'Keep-Alive', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache', 'User-Agent': 'MetaTrader 4 Terminal/4.1353 (Windows NT 6.1; x86)'}
b'{"name": "GOLDs","date_market": "2022-02-01T00:00:00.000000Z","period": "M1","open_price": 1797.64,"close_price": 1870.91,"low_price": 1788.33,"high_price": 1879.12,"bollinger_band":[{"period":"M1","moving_average_period":20,"standard_deviation":1.5,"high":1936.06829,"low":1717.61271,"moving_average":1826.8405},{"period":"M1","moving_average_period":20,"standard_deviation":2,"high":1972.47755,"low":1681.20345,"moving_average":1826.8405},{"period":"M1","moving_average_period":20,"standard_deviation":2.5,"high":2008.88681,"low":1644.79419,"moving_average":1826.8405}],"moving_average":[{"period":"M1","moving_average_period":50,"type": "0","value":1569.6854},{"period":"M1","moving_average_period":100,"type": "0","value":1399.8002},{"period":"M1","moving_average_period":200,"type": "0","value":1245.38985}],"MACD_zerolag":[{"period":"M1","fast_EMA_period":12,"slow_EMA_period":26,"signal_EMA_period":9,"histogram_value":-0.01794,"signal_value":0.09465,"MACD_value":0.07671}]}\x00'
所以我得到以下错误:
POST /api/symbol/ - 400
{'Content-Type': 'application/json', 'Vary': 'Accept', 'Allow': 'GET, POST, HEAD, OPTIONS'}
b'{"detail":"JSON parse error - Extra data: line 1 column 982 (char 981)"}'
如果使用 Postman 发送相同的数据删除 \x00 一切顺利。
mql4 客户端配置错误吗?
或者我可以删除接收到的数据来删除这个 \x00 吗?
这是我的 models.py
from django.db import models, transaction
M1 = 'M1'
M5 = 'M5'
M15 = 'M15'
M30 = 'M30'
H1 = 'H1'
H4 = 'H4'
DAILY = 'DAILY'
WEEKLY = 'WEEKLY'
MONTHLY = 'MONTHLY'
PERIOD_CHOICES = (
(M1, 'Une minute'),
(M5, 'Cinq minutes'),
(M15, 'Quinze minutes'),
(M30, 'Trente minutes'),
(H1, 'Une heure'),
(H4, 'Quatre heures'),
(DAILY, 'Journalier'),
(WEEKLY, 'Hebdomadaire'),
(MONTHLY, 'Mensuel'),
)
class BollingerBand(models.Model):
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
moving_average_period = models.CharField(max_length=8)
standard_deviation = models.DecimalField(max_digits=6, decimal_places=2)
symbol = models.ForeignKey('API.Symbol', on_delete=models.CASCADE, related_name='bollinger_band', default=1)
high = models.DecimalField(max_digits=12, decimal_places=6)
low = models.DecimalField(max_digits=12, decimal_places=6)
moving_average = models.DecimalField(max_digits=12, decimal_places=6)
class MovingAverage(models.Model):
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
moving_average_period = models.CharField(max_length=8)
type = models.TextField(max_length=30)
symbol = models.ForeignKey('API.Symbol', on_delete=models.CASCADE, related_name='moving_average', default=1)
value = models.DecimalField(max_digits=12, decimal_places=6)
class MACDZR(models.Model):
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
fast_EMA_period = models.CharField(max_length=4)
slow_EMA_period = models.CharField(max_length=4)
signal_EMA_period = models.CharField(max_length=4)
symbol = models.ForeignKey('API.Symbol', on_delete=models.CASCADE, related_name='MACD_zerolag', default=1)
histogram_value = models.DecimalField(max_digits=12, decimal_places=6)
signal_value = models.DecimalField(max_digits=12, decimal_places=6)
MACD_value = models.DecimalField(max_digits=12, decimal_places=6)
class Symbol(models.Model):
name = models.CharField(max_length=30, default='undefined')
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
date_market = models.DateTimeField()
period = models.CharField(max_length=30, choices=PERIOD_CHOICES, verbose_name='Période')
open_price = models.DecimalField(max_digits=12, decimal_places=6)
close_price = models.DecimalField(max_digits=12, decimal_places=6)
high_price = models.DecimalField(max_digits=12, decimal_places=6)
low_price = models.DecimalField(max_digits=12, decimal_places=6)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['name', 'date_market', 'period'],
name='unique_symbol'
)
]
def __str__(self):
return self.name
Serializers.py
from rest_framework import serializers
from API.models import Symbol, BollingerBand, MACDZR, MovingAverage
class BollingerBandSerializer(serializers.ModelSerializer):
class Meta:
model = BollingerBand
fields = ['period',
'moving_average_period',
'standard_deviation',
'symbol',
'high',
'low',
'moving_average']
class MovingAverageSerializer(serializers.ModelSerializer):
class Meta:
model = MovingAverage
fields = ['period',
'moving_average_period',
'type',
'symbol',
'value']
class MACDZRSerializer(serializers.ModelSerializer):
class Meta:
model = MACDZR
fields = ['period',
'fast_EMA_period',
'slow_EMA_period',
'signal_EMA_period',
'symbol',
'histogram_value',
'signal_value',
'MACD_value']
class SymbolSerializer(serializers.ModelSerializer):
bollinger_band = BollingerBandSerializer(many=True)
moving_average = MovingAverageSerializer(many=True)
MACD_zerolag = MACDZRSerializer(many=True)
class Meta:
model = Symbol
fields = ['id',
'name',
'date_created',
'date_updated',
'date_market',
'period',
'open_price',
'close_price',
'high_price',
'low_price',
'bollinger_band',
'moving_average',
'MACD_zerolag'
]
def create(self, validated_data):
bollinger_bands_data = validated_data.pop('bollinger_band')
moving_averages_data = validated_data.pop('moving_average')
MACDs_zerolag_data = validated_data.pop('MACD_zerolag')
symbol = Symbol.objects.create(**validated_data)
for bollinger_band_data in bollinger_bands_data:
BollingerBand.objects.create(symbol=symbol, **bollinger_band_data)
for MACD_zerolag_data in MACDs_zerolag_data:
MACDZR.objects.create(symbol=symbol, **MACD_zerolag_data)
for moving_average_data in moving_averages_data:
MovingAverage.objects.create(symbol=symbol, **moving_average_data)
return symbol
和settings.py
"""
Django settings for trading_project project.
Generated by 'django-admin startproject' using Django 4.0.2.
For more information on this file, see
https://docs.djangoproject.com/en/4.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.0/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-)6f&ci7@)t96(k^7am%66@%e%(88a%u00+3h5a13s461#q7dqm'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = [
'0.0.0.0',
'127.0.0.1',
]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#'django.contrib.sites',
'rest_framework',
'authentication',
'API',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'request_logging.middleware.LoggingMiddleware',
]
ROOT_URLCONF = 'trading_project.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates/'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'trading_project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'trading_project',
'USER': 'admin',
'PASSWORD': 'testpassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
# Password validation
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/
LANGUAGE_CODE = 'fr-fr'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.0/howto/static-files/
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
# Default primary key field type
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
AUTH_USER_MODEL = 'authentication.User'
LOGIN_URL = 'login'
LOGIN_REDIRECT_URL = 'home'
LOGOUT_URL = 'logout'
LOGOUT_REDIRECT_URL = 'login'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.request': {
'handlers': ['console'],
'level': 'DEBUG', # change debug level as appropiate
'propagate': False,
},
},
}
如果有人对此有简单的解决方案 谢谢
我找到了我的解决方案, 当我将数据字符串转换为 post_Data 对象时,长度不是 WHOLE_ARRAY,而是 StringLen.
StringToCharArray(data, post_data,0, StringLen(data));