I am using Django only for few weeks so there might be some mistakes.
I have an API using Django rest framework, which seems to work well. Using postman every thing is ok
I send data using WebRequest in Mql4 to the 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);
The data given to WebRequest is fine but the function add \x00 at the end of body.
Here is my post data when it arrive to Django rest framework
{'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'
so I get the following error :
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)"}'
if a send the same data removing the \x00 with Postman every thing goes well.
Is there a misconfiguration client side with mql4 ?
Or can I remove the received data to remove this \x00 ?
Here is my 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
and 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,
},
},
}
if anyone have a simple solution for that Thanks
I find my solution, when I converted my data string to post_Data object the length was not WHOLE_ARRAY, but StringLen.
StringToCharArray(data, post_data,0, StringLen(data));